SpringBoot整合Ldap--超详细方法讲解
LADP概述
LDAP(轻量目录访问协议)是一种用于访问和维护分布式目录信息服务的协议。目录服务是一种存储和检索信息的服务,通常用于存储组织内的用户信息、组织结构、网络设备等数据。LDAP是一种轻量级的协议,设计用于在目录中进行查找和修改操作,而不是用于传输大量的数据。
以下是LDAP的一些基本概念:
目录服务(Directory Service): 目录服务是一种专门设计用于存储和检索信息的服务。与传统数据库不同,目录服务更注重提供高效的读取操作,支持快速的数据检索。LDAP是一种协议,用于与目录服务进行通信。
目录(Directory): 目录是一种组织结构化数据的方式,通常包含多个条目(Entry)。每个条目包含一组属性值,用于描述特定实体(如用户、组织单位、设备等)的信息。
条目(Entry): 条目是目录中的基本单位,类似于数据库中的一行记录。每个条目都有一个唯一的标识符,称为DN(Distinguished Name)。
属性(Attribute): 属性是条目中存储的信息的命名和值对。例如,一个用户条目可能包含属性如姓名、电子邮件地址、电话号码等。
DN(Distinguished Name): DN是每个条目在目录中的唯一标识符,由一系列与目录结构相关的名称组成。DN通常是一个层次结构,例如"cn=john,ou=users,dc=example,dc=com"。
LDAP协议: LDAP定义了客户端和目录服务器之间进行通信的规则。它使用TCP/IP协议栈,通常在389端口上运行。LDAP协议支持多种操作,包括搜索、添加、删除、修改等,以便对目录中的数据进行操作。
LDAP被广泛用于企业和组织中,用于集中管理用户、组织结构、设备等信息。它是许多身份验证和访问控制系统的基础,如单点登录(SSO)系统。
步骤一:配置LDAP连接属性:
在application.properties或application.yml文件中添加LDAP连接属性,例如LDAP服务器URL、用户名、密码等。
步骤二:创建LDAP配置类:
创建一个@Configuration类,并使用@EnableWebSecurity注解启用Web安全性配置。在配置类中,可以使用LDAP的相关配置属性来配置LDAP连接和认证提供者。
步骤三:创建LDAP认证提供者:
实现UserDetailsService接口并重写其中的loadUserByUsername()方法,要在Spring Boot项目中整合LDAP(轻量级目录访问协议),可以使用Spring LDAP模块。以下是一个简单的示例,展示如何在Spring Boot中整合LDAP,并提供一些常见的操作示例。
整合步骤
1.引入POM依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
2.在application.properties或application.yml文件中提供LDAP连接的配置信息
ldap.url=ldap://your-ldap-server:389
ldap.base=dc=example,dc=com
ldap.userDnPattern=uid={0},ou=people
ldap.userSearchBase=ou=people
3.创建LdapDemoConfig
package com.example.springbootidapdemo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;@Configuration
public class LdapDemoConfig {@Beanpublic LdapTemplate ldapTemplate() {LdapContextSource contextSource = new LdapContextSource();contextSource.setUrl("ldap://localhost:389");contextSource.setBase("dc=example,dc=com");contextSource.setUserDn("cn=admin,dc=example,dc=com");contextSource.setPassword("adminpassword");contextSource.afterPropertiesSet();LdapTemplate ldapTemplate = new LdapTemplate(contextSource);ldapTemplate.setIgnorePartialResultException(true);ldapTemplate.setDefaultTimeLimit(1000);ldapTemplate.setDefaultCountLimit(100);return ldapTemplate;}
}
4.方法概述及对应Demo
前提:需要提供基础DN、过滤器、搜索控件和属性映射器。实际使用时,需要根据LDAP目录的结构和属性进行相应的配置。
1.ldapTemplate.find(根据指定的搜索条件在LDAP目录中查找条目并返回结果)
public <T> T find(String dn,String filter,SearchControls controls,AttributesMapper<T> mapper)
dn: 搜索的基础DN(Distinguished Name),表示搜索的起始位置。
filter: LDAP搜索过滤器,定义要匹配的条目的条件。
controls: 搜索控件,用于配置搜索的一些参数,例如搜索范围、返回的属性等。
mapper: 用于将搜索结果映射为对象的 AttributesMapper。
该方法会执行LDAP搜索并返回满足条件的第一个条目。如果没有匹配的条目,返回 null。
Demo如下:
@Service
public class LdapService {@Autowiredprivate LdapTemplate ldapTemplate;public User findUser(String username) {String baseDn = "ou=people,dc=example,dc=com";String filter = "(uid=" + username + ")";SearchControls controls = new SearchControls();controls.setSearchScope(SearchControls.SUBTREE_SCOPE);return ldapTemplate.find(baseDn, filter, controls, new UserAttributesMapper());}private static class UserAttributesMapper implements AttributesMapper<User> {@Overridepublic User mapFromAttributes(Attributes attributes) throws NamingException {return new User(/* user properties */);}}
}
下述demo只展示关键代码块、重复描述不再过多赘述
2.ldapTemplate.findAll(根据指定的搜索条件在LDAP目录中查找多个条目并返回结果列表)
public <T> List<T> findAll(String base,String filter,SearchControls controls,AttributesMapper<T> mapper)
base: 搜索的基础DN(Distinguished Name),表示搜索的起始位置。
该方法会执行LDAP搜索并返回满足条件的所有条目的列表。如果没有匹配的条目,返回空列表。
Demo如下:
public List<User> findAllUsers() {String baseDn = "ou=people,dc=example,dc=com";String filter = "(objectClass=person)"; SearchControls controls = new SearchControls();controls.setSearchScope(SearchControls.SUBTREE_SCOPE);return ldapTemplate.findAll(baseDn, filter, controls, new UserAttributesMapper());}
3.ldapTemplate.findOne(根据指定的搜索条件在LDAP目录中查找单个条目并返回结果)
注意:如果没有匹配的条目,抛出 javax.naming.NameNotFoundException 异常。如果有匹配的多个条目,抛出 javax.naming.NamingException 异常
public <T> T findOne(String dn,String filter,AttributesMapper<T> mapper)
Demo如下:
public User findUser(String username) {String baseDn = "ou=people,dc=example,dc=com";String filter = "(uid=" + username + ")";return ldapTemplate.findOne(baseDn, filter, new UserAttributesMapper());}
4.ldapTemplate.findByDn(根据给定的DN(Distinguished Name)查找单个条目并返回结果)
public <T> T findByDn(String dn, AttributesMapper<T> mapper)
该方法会执行LDAP搜索并返回指定DN的条目,如果没有找到匹配的条目,返回 null。
Demo如下:
public User findUserByDn(String userDn) {return ldapTemplate.findByDn(userDn, new UserAttributesMapper());}
5.ldapTemplate.findForStream(用于从 LDAP 目录中以流的方式获取多个条目的结果)
public <T> Stream<T> findForStream(String base,String filter,SearchControls controls,AttributesMapper<T> mapper)
ldapTemplate.findForStream方法会执行LDAP搜索并返回一个流(Stream),其中包含满足条件的所有条目的结果。通过使用流的方式,可以更高效地处理大量的搜索结果,而不必一次性将所有结果加载到内存中。
Demo如下:
public List<User> findAllUsers() {String baseDn = "ou=people,dc=example,dc=com";String filter = "(objectClass=person)";SearchControls controls = new SearchControls();controls.setSearchScope(SearchControls.SUBTREE_SCOPE);Stream<User> userStream = ldapTemplate.findForStream(baseDn, filter, controls, new UserAttributesMapper());return userStream.collect(Collectors.toList());}
注意:ldapTemplate.findForStream 方法是从 Spring LDAP 2.2 版本开始引入的。确保使用的是兼容的 Spring LDAP 版本。如果版本较旧,可能需要升级到兼容的版本或者使用其他方法来处理 LDAP 搜索结果流
6.ldapTemplate.search(用于执行灵活的LDAP搜索并返回结果)
public <T> List<T> search(String base,String filter,SearchControls controls,AttributesMapper<T> mapper)
与之前介绍的
ldapTemplate.findAll方法相似,ldapTemplate.search方法也执行LDAP搜索,但它提供更多的灵活性,可以更精确地配置搜索参数。该方法返回满足条件的所有条目的列表。
Demo如下:
public List<User> searchUsers(String filter) {String baseDn = "ou=people,dc=example,dc=com";SearchControls controls = new SearchControls();controls.setSearchScope(SearchControls.SUBTREE_SCOPE);return ldapTemplate.search(baseDn, filter, controls, new UserAttributesMapper());}
7.ldapTemplate.searchForContext(用于执行LDAP搜索并返回搜索结果的上下文(DirContext))
public DirContext searchForContext(String base,String filter,SearchControls controls)
与之前介绍的
ldapTemplate.search方法相比ldapTemplate.searchForContext返回的是搜索结果的上下文,而不是直接返回映射后的对象列表。这样的设计使得可以更灵活地处理搜索结果,包括对搜索结果的进一步处理、解析和操作。
Demo如下:
public DirContext searchForContext(String filter) {String baseDn = "ou=people,dc=example,dc=com";SearchControls controls = new SearchControls();controls.setSearchScope(SearchControls.SUBTREE_SCOPE);return ldapTemplate.searchForContext(baseDn, filter, controls);}
8.ldapTemplate.searchForObject(用于执行LDAP搜索并返回单个对象作为结果)
public <T> T searchForObject(String base,String filter,SearchControls controls,Class<T> requiredType)
requiredType: 期望的返回类型。
该方法执行LDAP搜索并返回单个对象,而不是返回一个对象列表。这可以方便地用于查找特定条件下的唯一条目。
Demo如下:
public User searchForUser(String username) {String baseDn = "ou=people,dc=example,dc=com";String filter = "(uid=" + username + ")";SearchControls controls = new SearchControls();controls.setSearchScope(SearchControls.SUBTREE_SCOPE);return ldapTemplate.searchForObject(baseDn, filter, controls, User.class);}
注意:如果没有找到匹配的条目,ldapTemplate.searchForObject 方法将返回 null
9.ldapTemplate.searchForStream(用于执行LDAP搜索并返回结果的流(Stream))
public <T> Stream<T> searchForStream(String base,String filter,SearchControls controls,Class<T> requiredType)
该方法执行LDAP搜索并返回一个流(Stream),其中包含满足条件的所有条目的结果。通过使用流的方式,可以更高效地处理大量的搜索结果,而不必一次性将所有结果加载到内存中。
Demo如下:
public List<User> searchForUsers(String filter) {String baseDn = "ou=people,dc=example,dc=com";SearchControls controls = new SearchControls();controls.setSearchScope(SearchControls.SUBTREE_SCOPE);Stream<User> userStream = ldapTemplate.searchForStream(baseDn, filter, controls, User.class);return userStream.collect(Collectors.toList());}
10.ldapTemplate.rebind(用于重新绑定(更新)LDAP目录中的条目)
public void rebind(String dn, Object obj, Attributes attributes)
obj: 要重新绑定的对象。
该方法会将指定的对象和属性重新绑定到LDAP目录中的指定DN。如果指定的DN不存在,则会创建新的条目。如果已存在具有相同DN的条目,则会更新现有条目的属性。
public void updateUserInfo(String userDn, User newUser) {// Assume User class has appropriate getters and setters for user attributesAttributes attributes = // create or update attributes based on newUserldapTemplate.rebind(userDn, newUser, attributes);}
注意:具体的 Attributes 对象的创建或更新需要根据您的数据模型和需求进行调整
11.ldapTemplate.rename(用于重命名(移动)LDAP目录中的条目)
public void rename(String oldDn, String newDn)
oldDn: 要重命名的旧DN,表示LDAP目录中的一个条目。
newDn: 新的DN,表示条目在LDAP目录中的新位置。
该方法会将指定的条目从旧的DN移动到新的DN,实现重命名的效果。
Demo如下:
public void renameUser(String oldDn, String newDn) {ldapTemplate.rename(oldDn, newDn);}
注意:新的DN必须包含新的父级DN,以确保条目被正确移动到新的位置。例如,如果要将用户从 "ou=people,dc=example,dc=com" 移动到"ou=otherPeople,dc=example,dc=com",则新的DN应为"uid=john,ou=otherPeople,dc=example,dc=com"。
12.ldapTemplate.modifyAttributes(用于修改LDAP目录中条目的属性值)
public void modifyAttributes(String dn, ModificationItem[] mods)
mods: 要应用的修改项数组,表示要对条目进行的修改操作。
修改项(ModificationItem)由两个属性组成:修改操作类型(DirContext.ADD_ATTRIBUTE、DirContext.REMOVE_ATTRIBUTE 或 DirContext.REPLACE_ATTRIBUTE)和要修改的属性(Attribute)。
Demo如下:
public void updateUserPassword(String userDn, String newPassword) {ModificationItem[] mods = new ModificationItem[1];Attribute attribute = new BasicAttribute("userPassword", newPassword);mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attribute);ldapTemplate.modifyAttributes(userDn, mods);}
上述示例中,
updateUserPassword方法使用了ldapTemplate.modifyAttributes来根据用户DN(userDn)修改用户密码。首先,创建一个ModificationItem数组,包含要进行的修改操作。在这个示例中,它只包含一项:用新密码替换(DirContext.REPLACE_ATTRIBUTE)userPassword属性。然后,将这个修改项数组传递给ldapTemplate.modifyAttributes方法,以便进行修改
13.ldapTemplate.authenticate(用于对LDAP进行认证操作)
public boolean authenticate(String base, String filter, String password)
password: 用户密码,用于认证操作。
该方法用于验证给定的用户密码是否与LDAP中指定条件的用户匹配。如果匹配成功,则返回 true,否则返回 false。
Demo如下:
public boolean authenticateUser(String username, String password) {String baseDn = "ou=people,dc=example,dc=com";String filter = "(uid=" + username + ")";return ldapTemplate.authenticate(baseDn, filter, password);}
上述示例中,
authenticateUser方法使用了ldapTemplate.authenticate来验证用户的身份。需要提供基础DN、过滤器和用户密码。该方法将验证提供的用户名和密码是否匹配LDAP中指定条件的用户,如果匹配成功,则返回 true,表示认证通过。
相关文章:
SpringBoot整合Ldap--超详细方法讲解
LADP概述 LDAP(轻量目录访问协议)是一种用于访问和维护分布式目录信息服务的协议。目录服务是一种存储和检索信息的服务,通常用于存储组织内的用户信息、组织结构、网络设备等数据。LDAP是一种轻量级的协议,设计用于在目录中进行查…...
【工程实践】Docker使用记录
前言 服务上线经常需要将服务搬到指定的服务器上,经常需要用到docker,记录工作中使用过dcoker指令。 1.写Dockerfile 1.1 全新镜像 FROM nvidia/cuda:11.7.1-devel-ubuntu22.04ENV WORKDIR/data/Qwen-14B-Chat WORKDIR $WORKDIR ADD . $WORKDIR/RUN ap…...
FreeSwitch安装视频
文章目录 序言Centos7安装FreeSwitch-1.6 序言 学习资料来源《FreeSWITCH权威指南》-作者杜金房这本书。我是2022年6月毕业的,偶然的机会接触到FreeSWITCH,FreeSWITCH纯属个人爱好,进行笔记整理。也一直希望有机会可以参与FreeSWITCH相关工作…...
SpringBoot3+Vue3+Mysql+Element Plus完成数据库存储blob类型图片,前端渲染后端传来的base64类型图片
前言 如果你的前后端分离项目采用SpringBoot3Vue3Element Plus,且在没有OSS(对象存储)的情况下,使用mysql读写图片(可能不限于图片,待测试)。 耗时三天,在踩了无数雷后,…...
攻略 | 参与Moonbeam Ignite Ecosystem Tour
Moonbeam联合Moonwell和Beamswap一起举办社区链上活动,旨在让社区用户通过任务来探索Moonbeam、Moonwell、Beamswap平台。在了解如何使用的同时,参与任务挑战还有机会分得 1700 USDC 奖池 🎁 的奖励!我已经完成全部任务࿰…...
【python自动化】Playwright基础教程(七)Keyboard键盘
【python自动化】Playwright基础教程(七)Keyboard键盘 playwright模拟键盘操作 键盘事件提供了用于管理虚拟键盘的API,高级API是keyboard.type(),它使用的是原始字符再页面上生成对应的keydown 、 keypress / input 和 keyup 事件。 模拟真实键盘操作进行…...
Java读取文件内容写入新文件
要实现读写文件这个过程我们需要导入以下的包 import java.io.BufferedReader; import java.io.BufferedWriter;BufferedReader 用于逐行读取源文件的内容,BufferedWriter 用于逐行写入目标文件。 下面以示例了解如何操作: import java.io.BufferedRe…...
学习samba
文章目录 一、samba介绍二、samba的主要进程三、配置文件四、例子 一、samba介绍 1、SMB(Server Message Block)协议实现文件共享,也称为CIFS(Common Internet File System)。 2、是Windows和类Unix系统之间共享文件的…...
【Ansible】Ansible的Ad-hoc命令执行流程
Ansible的Ad-hoc命令执行流程 用了这么久的Ansible,今天想着研究下Ad-hoc命令的执行流程,从最简单的ping开始吧。 测试命令如下: ansible 172.18.2.31 -m ping先看看回显的结果 [rootbigdata-m-002 etc]# ansible 172.18.2.31 -m ping 17…...
Postgresql 常用整理
文章目录 1. 查询1.1数据库表1.1.1 获取指定数据库表1.1.2 获取指定数据库表所有列名 1.2 别名1.2.1 子表指定别名1.2.2 查询结果指定别名 1.3 临时表1.3.1 定义临时表1.3.2 使用临时表 1.4 子表1.5 分组1.5.1 group by1.5.2 partition by 1.6 分组后合并指定列字段:…...
如何在Jupyter Lab中安装不同的Kernel
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
Java钩子函数的使用
目录 1. Java中常见的钩子函数 2. 使用钩子函数实现程序的清理工作 3. 使用钩子函数处理线程中的未捕获异常 4. 使用钩子函数实现窗口关闭时的操作 在Java编程中,钩子函数(Hook Function)是一种能够在特定事件发生时执行的代码块。钩子函…...
C++跨DLL内存所有权问题探幽(一)DLL提供的全局单例模式
最近在开发的时候,特别是遇到关于跨DLL申请对象、指针、内存等问题的时候遇到了这么一个问题。 问题 跨DLL能不能调用到DLL中提供的单例? 问题比较简单,就是我现在有一个进程A,有DLL B DLL C,这两个DLL都依赖DLL D的…...
短时间不点击云服务器,自动化断开连接,怎么设置长时间
在 Linux 系统中,如果你希望在一段时间内没有操作后保持远程连接不断开,可以通过修改 SSH 服务器的配置来实现。具体的步骤如下: 打开 SSH 服务器的配置文件: sudo vi /etc/ssh/sshd_config 找到以下两个参数并进行修改ÿ…...
typhonjs-escomplex 代码可读性 可维护度探索
目前市面上的前端代码质量评分中的代码可维护度是大都是基于 typhonjs-escomplex 这个库扫描而来,但是这个库的官方文档并没有介绍相关指标数据的计算规则,不知道规则如何提升指标数据呢?所以本文对 typhonjs-escomplex 源码进行探索…...
支持向量机基本原理,Libsvm工具箱详细介绍,基于支持向量机SVM的人脸朝向识别
目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 完整代码和数据下载链接: 基于支持向量机SVM人脸朝向识别(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88527821 SVM应用实例, 基…...
密码破解工具的编写
预计更新 网络扫描工具的编写漏洞扫描工具的编写Web渗透测试工具的编写密码破解工具的编写漏洞利用工具的编写拒绝服务攻击工具的编写密码保护工具的编写情报收集工具的编写 密码破解工具是一种常见的安全工具,它可以通过不断尝试不同的密码组合来破解加密的数据或…...
BES2700H开发不完全手册
BES2700H开发不完全手册 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,群赠送语音信号处理降噪算法,ANC AEC ENC EQ BF BES蓝牙耳机音频资料 1 成功编译 2 代码 3 开放文档...
OpenGL的学习之路-3
前面1、2介绍的都是glut编程 下面就进行opengl正是部分啦。 1.绘制点 #include <iostream> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h>void myMainWinDraw();int main(int argc,char** argv) {glutInit(&argc,argv);glutIni…...
Vue 小黑记事本组件版
渲染功能: 1.提供数据: 提供在公共的父组件 App.vue 2.通过父传子,将数据传递给TodoMain 3.利用 v-for渲染 添加功能: 1.收集表单数据 v-model 2.监听事件(回车点击都要添加) 3.子传父,讲…...
PFC5.0代码:含三种矿物组成的岩石或类岩石材料GBM单轴压缩2d算例代码,仅供学习与提升
PFC5.0代码,含三种矿物组成的岩石或者类岩石材料,GBM,单轴压缩2d,算例代码仅供学习以及提升 打开PFC5.0的建模界面,突然想把花岗岩里的石英、长石、云母做成颗粒组合。先整点暴力的——直接拿球体颗粒拼成矿物晶粒&…...
万象视界灵坛惊艳案例:浅蓝格点背景中生成的‘同步率’进度条动态响应过程
万象视界灵坛惊艳案例:浅蓝格点背景中生成的"同步率"进度条动态响应过程 1. 效果展示概述 在视觉识别领域,传统界面往往显得单调乏味。万象视界灵坛通过创新的像素风格设计,将复杂的语义对齐过程转化为一场视觉盛宴。本次展示的核…...
YOLOv12模型轻量化实战:应对嵌入式设备资源约束
YOLOv12模型轻量化实战:应对嵌入式设备资源约束 最近几年,目标检测模型在精度上突飞猛进,但随之而来的是模型体积和计算量的急剧膨胀。当你兴冲冲地想把最新的YOLOv12模型部署到Jetson Nano或者树莓派上时,往往会发现现实很骨感&…...
Pixel Aurora Engine效果展示:像素极光视觉系统渲染的星际战舰系列
Pixel Aurora Engine效果展示:像素极光视觉系统渲染的星际战舰系列 1. 像素极光引擎简介 Pixel Aurora Engine是一款基于AI扩散模型的高端绘图工作站,专为像素艺术创作而设计。它采用独特的复古像素游戏风格界面,通过先进的AI技术将文字描述…...
共享图书借阅系统 Java 源码 + 数据库设计完整方案
以下是一个共享图书借阅系统的Java源码与数据库设计的完整方案,涵盖系统架构、核心功能实现、数据库设计以及安全防护措施等方面:一、系统架构技术栈:后端:Spring Boot 2.x MyBatis-Plus(简化数据库操作)前…...
FORK客户端与GitHub高效协作指南
1. 为什么选择FORK客户端与GitHub协作 作为一个常年混迹在代码仓库的老司机,我试过几乎所有主流的Git图形化工具。FORK客户端给我的第一印象就是——清爽。没有复杂的界面,没有多余的功能,就像它的名字一样,专注做好代码分支管理…...
Zigbee网关配网操作全解析:从连接到触发
1. Zigbee网关配网前的准备工作 第一次接触Zigbee网关配网的朋友可能会觉得有点复杂,但其实只要跟着步骤一步步来,整个过程并不难。我刚开始接触时也踩过不少坑,现在把这些经验都整理出来,希望能帮你少走弯路。 首先得确认你的硬件…...
Isaac Sim 4.1.0 国内网络环境下的三种下载与安装提速方案(含离线包处理)
Isaac Sim 4.1.0 国内网络环境下的高效安装指南 对于国内开发者而言,安装NVIDIA Isaac Sim往往面临下载速度缓慢、连接不稳定等问题。本文将提供三种经过验证的解决方案,帮助您快速完成安装。 1. 直链下载加速方案 通过分析Omniverse Launcher的日志文件…...
PyTorch 2.8镜像一文详解:xFormers+Accelerate+Diffusers全栈预装环境实测
PyTorch 2.8镜像一文详解:xFormersAccelerateDiffusers全栈预装环境实测 1. 镜像概述与核心优势 PyTorch 2.8深度学习镜像是一个经过深度优化的全栈AI开发环境,专为现代深度学习任务设计。这个镜像最显著的特点是开箱即用的完整工具链支持,…...
pngquant终极错误排查手册:10个常见问题与快速解决方案
pngquant终极错误排查手册:10个常见问题与快速解决方案 【免费下载链接】pngquant Lossy PNG compressor — pngquant command based on libimagequant library 项目地址: https://gitcode.com/gh_mirrors/pn/pngquant pngquant作为一款高效的PNG有损压缩工具…...
