java连接kerberos用户认证
java连接kerberos用户认证
@toc
一、背景
亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍报错以及配置用处,根本不懂照抄那些配置是干啥的,稀里糊涂的按照博客搭完也跑不起来,因此记录这个。
项目背景
:公司项目当前采用http协议+shiro+mysql的登录认证方式,而现在想支持ldap协议认证登录然后能够访问自己公司的项目网站。
举例说明
:假设我们公司有自己的门户网站,现在我们收购了一家公司,他们数据库采用ldap存储用户数据,那么为了他们账户能登陆我们公司项目所以需要集成,而不是再把他们的账户重新在mysql再创建一遍,万一人家有1W个账户呢,不累死了且也不现实啊。
需要安装openldap+kerberos,且ldap和kerberos安装在同一台服务器上,当前版本如下:
centos 7.9
openldap 2.4.44
phpldapadmin 1.2.5
服务器IP:10.110.8.162
Kerberos :Kerberos 5 release 1.15.1
另外介绍下我的Spring各个版本:
Spring Security:4.2..RELEASE
Spring Version:4..9.RELEASE
SpringBoot Version:1.4.7.RELEASE
注意点1:
我之所以选这么旧的版本,是因为我最后要在自己项目集成,我们项目就是上面版本附近的,所以不能选太高版本,这点请注意各版本之间的兼容性问题。
详情可看这篇博客介绍兼容版本:
注意点2
:如果里面的某些配置不知道在哪或者不知道干啥的,可以看我的前面的博客,详细介绍了安装配置等,可以大致了解参数。
目前网上相关文章很少,而且好多博客都是未认证就发布的所以一堆问题,跑不起来,如下是我参考的博客
- Spring Security Kerberos - Reference Documentation
- MIT Kerberos Documentation
- /
- Authentication Protocols: LDAP vs Kerberos vs OAuth2 vs SAML vs RADIUS
二、代码
server.port=8020
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=".0.0" xmlns:xsi=";
xsi:schemaLocation=".0.0 .0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>1.4.7.RELEASE</version>
</parent>
<groupId></groupId>
<artifactId>ldap-test2</artifactId>
<version>0.0.1-SAPSHOT</version>
<name>ldap-test2</name>
<description>Demo project for Spring Boot</description>
<properties>
<mavenpiler.source>8</mavenpiler.source>
<>8</>
</properties>
<dependencies>
<!--解决@RestController注解爆红-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<!--测试类-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<exclusi>
<exclusion>
<artifactId>spring-security-core</artifactId>
<groupId>org.springframework.security</groupId>
</exclusion>
</exclusi>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
<version>2.6.</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-ldap</artifactId>
<version>2.6.</version>
</dependency>
<dependency>
<groupId>com.sun</groupId>
<artifactId>ldapbp</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-all</artifactId>
<version>2.0.0</version>
</dependency>
<!-- Spring Security Kerberos -->
<dependency>
<groupId>org.springframework.security.kerberos</groupId>
<artifactId>spring-security-kerberos-core</artifactId>
<version>1.0.1.RELEASE</version>
<exclusi>
<exclusion>
<artifactId>spring-security-core</artifactId>
<groupId>org.springframework.security</groupId>
</exclusion>
</exclusi>
</dependency>
<dependency>
<groupId>org.springframework.security.kerberos</groupId>
<artifactId>spring-security-kerberos-client</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.kerberos</groupId>
<artifactId>spring-security-kerberos-web</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<!-- Additional dependencies for Spring LDAP and Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>4.2..RELEASE</version>
<exclusi>
<exclusion>
<artifactId>spring-security-core</artifactId>
<groupId>org.springframework.security</groupId>
</exclusion>
</exclusi>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2..RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>.ldaptest2.LdapTest2Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
AuthProviderConfig配置类
说明:
注释的代码还没放开,目前只是demo阶段,后续需要集成到自己项目 ,肯定需要配置哪些路径访问权限放开,如果没权限自动跳转项目登录页等等,后续需要再配置的。
package .;
import .ldaptest2.service.DummyUserDetailsService;
import org.annotation.Bean;
import org.annotation.Configuration;
import org.springframework.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.annotation.web.builders.HttpSecurity;
import org.springframework.annotation.WebSecurityConfigurerAdapter;
import org.springframework.annotation.web.EnableWebMvcSecurity;
import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider;
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient;
@Configuration
@EnableWebMvcSecurity
public class AuthProviderConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/ldap/*").permitAll()
.anyRequest().authenticated();
// .and()
// .formLogin()
// .loginPage("/login").permitAll()
// .and()
// .logout()
// .permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(kerberosAuthenticationProvider());
}
@Bean
public KerberosAuthenticationProvider kerberosAuthenticationProvider() {
KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider();
SunJaasKerberosClient client = new SunJaasKerberosClient();
client.setDebug(true);
provider.setKerberosClient(client);
provider.setUserDetailsService(dummyUserDetailsService());
return provider;
}
@Bean
public DummyUserDetailsService dummyUserDetailsService() {
return new DummyUserDetailsService();
}
}
CustomConfigurationByKeytab配置类
代码语言:java复制package .;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @Author 211145187
* @Date 2024/6/1 16:4
**/
// 自定义 Configuration 类,用于提供 Kerberos 登录配置
public class CustomConfigurationByKeytab extends Configuration {
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
if ("KrbLogin".equals(name)) {
Map<String, String> opti = new HashMap<>();
opti.put("useKeyTab", "true"); //指定是否使用 keytab 文件进行登录,这里设置为 true,表示使用 keytab 文件。
opti.put("keyTab", "C:\\Users\\211145187\\Desktop\\fsdownload\\ldap.keytab"); //指定 keytab 文件的路径,这里设置为 "/etc/openldap/ldap.keytab"。
// opti.put("keyTab", "/etc/openldap/ldap.keytab"); //指定 keytab 文件的路径,这里设置为 "/etc/openldap/ldap.keytab"。
opti.put("storeKey", "true"); //指定是否将密钥存储在 Subject 中,这里设置为 true,表示存储密钥。
opti.put("useTicketCache", "false"); //指定是否使用票据缓存,这里设置为 false,表示不使用票据缓存。
opti.put("dootPrompt", "true"); //指定是否禁止提示用户输入用户名和密码,这里设置为 true,表示禁止提示。
opti.put("debug", "true"); //指定是否启用调试模式,这里设置为 true,表示启用调试模式。
opti.put("principal", "ldapadmin@ODE.COM"); //指定要使用的主体名称,这里设置为 "ldap/bridge1@ODE.COM",表示使用的服务主体。
// 定义 Kerberos 登录模块的配置项
AppConfigurationEntry entry = new AppConfigurationEntry(
"com.sun.security.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
opti
);
return new AppConfigurationEntry[]{entry};
}
return null;
}
}
CustomConfigurationByPassword配置类
代码语言:java复制package .;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @Author 211145187
* @Date 2024/6/1 16:4
**/
// 自定义 Configuration 类,用于提供 Kerberos 登录配置
public class CustomConfigurationByPassword extends Configuration {
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
if ("KrbLogin".equals(name)) {
Map<String, String> opti = new HashMap<>();
opti.put("useKeyTab", "false"); //指定是否使用 keytab 文件进行登录,这里设置为 true,表示使用 keytab 文件。
opti.put("storeKey", "true"); //指定是否将密钥存储在 Subject 中,这里设置为 true,表示存储密钥。
opti.put("useTicketCache", "false"); //指定是否使用票据缓存,这里设置为 false,表示不使用票据缓存。
opti.put("dootPrompt", "false"); //指定是否禁止提示用户输入用户名和密码,这里设置为 true,表示禁止提示。
opti.put("debug", "true"); //指定是否启用调试模式,这里设置为 true,表示启用调试模式。
opti.put("password", "12456"); //指定要使用的主体名称,这里设置为 "ldap/bridge1@ODE.COM",表示使用的服务主体。
opti.put("principal", "testldap@ODE.COM"); //指定要使用的主体名称,这里设置为 "ldap/bridge1@ODE.COM",表示使用的服务主体。
// 定义 Kerberos 登录模块的配置项
AppConfigurationEntry entry = new AppConfigurationEntry(
"com.sun.security.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
opti
);
return new AppConfigurationEntry[]{entry};
}
return null;
}
}
TestController
注意:其实这个controller可有可无,因为你写java客户端连接kerberos,如果不涉及打包部署linux环境通过url方式掉方法,完全可以不写这个,只写本地测试方法即可。
代码语言:java复制package .;
import ..CustomConfigurationByKeytab;
import ..CustomConfigurationByPassword;
import .LdapUser;
import .MyCallbackHandler;
import .LdapUserAttributeMapper;
import com.sun.apache.xerces.internal.impl.dv.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.security.MessageDigest;
import java.;
import java.util.List;
/**
* @Author 211145187
* @Date 2024/6/14 17:18
**/
@RestController
@RequestMapping("/ldap")
public class TestController {
private static Logger logger = LoggerFactory.getLogger();
//keytab认证
@GetMapping(value = "/authenticateUserByKeytab")
public void authenticateUserByKeytab() {
try {
System.setProperty("java.security.", "/etc/");
// 创建 LoginContext 对象,并为其提供自定义 Configuration
LoginContext lc = new LoginContext("KrbLogin", null, null, new CustomConfigurationByKeytab());
// 进行 Kerberos 认证
lc.login();
// 获取 Subject
Subject subject = lc.getSubject();
// logger.info("subject:{}", subject);
// 在这里可以使用 subject 来执行进一步的操作,如访问受限资源
// 登出
lc.logout();
} catch (LoginException e) {
// 处理登录异常
e.printStackTrace();
("LoginException e:{}", e.getMessage());
}
}
//用户+密码认证
@GetMapping(value = "/authenticateUserByPassword")
public void authenticateUserByPassword() {
try {
System.setProperty("java.security.", "/etc/");
// 创建 LoginContext 对象,并为其提供自定义 Configuration
LoginContext lc = new LoginContext("KrbLogin", null, new MyCallbackHandler(), new CustomConfigurationByPassword());
// 进行 Kerberos 认证
lc.login();
// 获取 Subject
Subject subject = lc.getSubject();
// logger.info("subject:{}", subject);
// 在这里可以使用 subject 来执行进一步的操作,如访问受限资源
// 登出
lc.logout();
} catch (LoginException e) {
// 处理登录异常
e.printStackTrace();
("LoginException e:{}", e.getMessage());
}
}
@GetMapping(value = "/test")
public String test() {
return "Hello";
}
}
MyCallbackHandler
代码语言:java复制package .;
import javax.security.Callback;
import javax.security.CallbackHandler;
import javax.security.ameCallback;
import javax.security.PasswordCallback;
import javax.security.UnsupportedCallbackException;
/**
* @Author 211145187
* @Date 2024/6/1 19:18
**/
public class MyCallbackHandler implements CallbackHandler {
@Override
public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
for (Callback callback : callbacks) {
if (callback instanceof ameCallback) {
// 处理用户名回调
ameCallback nc = (ameCallback) callback;
nc.setame("ldapadmin@ODE.COM"); // 设置用户名
} else if (callback instanceof PasswordCallback) {
// 处理密码回调
PasswordCallback pc = (PasswordCallback) callback;
pc.setPassword("12456".toCharArray()); // 设置密码
} else {
throw new UnsupportedCallbackException(callback, "Unrecognized Callback");
// 其他类型的回调
// 可以根据需要处理其他类型的回调
}
}
}
}
DummyUserDetailsService实现类
代码语言:java复制package .ldaptest2.service;
import org.springframework.authority.AuthorityUtils;
import org.springframework.userdetails.User;
import org.springframework.userdetails.UserDetails;
import org.springframework.userdetails.UserDetailsService;
import org.springframework.userdetails.UsernameotFoundException;
/**
* @Author 211145187
* @Date 2024/6/1 15:7
**/
public class DummyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameotFoundException {
return new User(username, "notUsed", true, true, true, true,
("ROLE_USER"));
}
}
LdapTest2Application启动类
代码语言:java复制package .ldaptest2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LdapTest2Application {
public static void main(String[] args) {
SpringApplication.run(, args);
}
}
KerberosTest测试类
代码语言:java复制package .ldaptest2;
import ..CustomConfigurationByKeytab;
import ..CustomConfigurationByPassword;
import .MyCallbackHandler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.SpringBootTest;
import org.junit4.SpringRunner;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
@SpringBootTest
@RunWith()
public class KerberosTest {
private static Logger logger = LoggerFactory.getLogger();
//用户+密码认证
@Test
public void authenticateUserByPassword() {
try {
System.setProperty("java.security.", "C:\\Users\\211145187\\Desktop\\fsdownload\\");
// 创建 LoginContext 对象,并为其提供自定义 Configuration
LoginContext lc = new LoginContext("KrbLogin", null, new MyCallbackHandler(), new CustomConfigurationByPassword());
// 进行 Kerberos 认证
lc.login();
// 获取 Subject
Subject subject = lc.getSubject();
// logger.info("subject:{}", subject);
// 在这里可以使用 subject 来执行进一步的操作,如访问受限资源
// 登出
lc.logout();
} catch (LoginException e) {
// 处理登录异常
e.printStackTrace();
}
}
//keytab认证
@Test
public void authenticateUserByKeytab() {
try {
System.setProperty("java.security.", "C:\\Users\\211145187\\Desktop\\fsdownload\\");
// 创建 LoginContext 对象,并为其提供自定义 Configuration
LoginContext lc = new LoginContext("KrbLogin", null, null, new CustomConfigurationByKeytab());
// 进行 Kerberos 认证
lc.login();
// 获取 Subject
Subject subject = lc.getSubject();
// logger.info("subject:{}", subject);
// 在这里可以使用 subject 来执行进一步的操作,如访问受限资源
// 登出
lc.logout();
} catch (LoginException e) {
// 处理登录异常
e.printStackTrace();
}
}
}
SpringVersionUtils测试类
代码语言:java复制package .ldaptest2;
import org.junit.Test;
import org.springframework.boot.SpringBootVersion;
import org.SpringVersion;
import org.springframework.SpringSecurityCoreVersion;
/**
* 获取Spring、SpringBoot版本号
* @Author 211145187
* @Date 2022/11/12 10:42
**/
public class SpringVersionUtils {
/**
* Spring Security:4.2..RELEASE
* Spring Version:4..9.RELEASE
* SpringBoot Version:1.4.7.RELEASE
*/
@Test
public void getSpringVersion() {
println("Spring Security:" + SpringSecurityCoreVersion.getVersion());
String versionSpring = SpringVersion.getVersion();
String versionSpringBoot = SpringBootVersion.getVersion();
println("Spring Version:" + versionSpring);
println("SpringBoot Version:" + versionSpringBoot);
}
}
六、其他报错可参考文档
Kerberos相关问题进行故障排除| 常见错误和解决方法
本人其他相关文章链接
1.Centos7.9安装openldap
2.Centos7.9安装kerberos
.Openldap集成Kerberos
4.Centos7.9安装phpldapadmin
5.java连接ldap实现用户查询功能
6.java连接kerberos用户认证
7.javax.security.auth.login.LoginException: Unable to obtain password from user
8.javax.security.auth.login.LoginException: null (68)
9.javax.security.auth.login.LoginException: Message stream modified (41)
10.javax.security.auth.login.LoginException: Checksum failed
11.javax.security.auth.login.LoginException: o CallbackHandler available to garner authentication info
12.javax.security.auth.login.LoginException: Cannot locate KDC
1.javax.security.auth.login.LoginException: Receive timed out
14.java: 无法访问org.ConfigurableApplicationContext
15.LDAP: error code 4 - invalid D
16.LDAP: error code 2 - o Such Object
17.java: 无法访问org.springframework.LdapTemplate
18.windows server2016搭建AD域服务器
19.java连接AD(Microsoft Active Directory)模拟用户登录认证
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 13 条评论) |
本站网友 化妆品广告 | 1秒前 发表 |
这里设置为 true | |
本站网友 中堂海陆汇 | 26分钟前 发表 |
Unable to obtain password from user8.javax.security.auth.login.LoginException | |
本站网友 218219 | 22分钟前 发表 |
需要安装openldap+kerberos | |
本站网友 兰州二手房出售信息 | 5分钟前 发表 |
之前搜索了很多博客 | |
本站网友 福建海峡整形医院 | 14分钟前 发表 |
"true"); //指定是否启用调试模式 | |
本站网友 flash背景 | 3分钟前 发表 |
这里设置为 true | |
本站网友 9700 | 2分钟前 发表 |
这点请注意各版本之间的兼容性问题 | |
本站网友 南汇租房 | 9分钟前 发表 |
7 **/ public class DummyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameotFoundException { return new User(username | |
本站网友 城市公共设施 | 25分钟前 发表 |
Cannot locate KDC1.javax.security.auth.login.LoginException | |
本站网友 萨伦冰淇淋 | 10分钟前 发表 |
new CustomConfigurationByPassword()); // 进行 Kerberos 认证 lc.login(); // 获取 Subject Subject subject = lc.getSubject(); // logger.info("subject | |
本站网友 行为主义疗法 | 1秒前 发表 |
"true"); //指定是否启用调试模式 | |
本站网友 大连铁通星海影院 | 12分钟前 发表 |
详细介绍了安装配置等 |