Mac本地Java Web应用实现Windows集成认证SSO技术咨询
嘿,刚好有过类似的配置经验,针对你在Mac上运行的Java Web应用要对接Windows集成认证SSO的需求,结合你现有OpenLDAP的架构,我整理了一套落地性很强的方案:
核心思路
Windows集成认证SSO的核心是Kerberos+SPNEGO协议:Kerberos负责和Windows域控制器完成身份票据的签发与验证,SPNEGO则把Kerberos认证适配到HTTP层面,让浏览器能自动传递用户的域身份。同时我们要把这套流程和你现有的OpenLDAP用户体系打通,确保认证通过后能正确关联到应用内的用户权限。
一、前提准备先搞定
- 确保你的Windows域(AD)和Mac上的OpenLDAP能互通:要么OpenLDAP已经同步了AD的用户数据,要么后续我们通过Kerberos认证后,再去OpenLDAP拉取用户的详细信息/权限。
- Mac机器要能和域控制器正常通信:可以ping通域控IP,DNS能解析域控的主机名。
- JDK版本建议用8及以上,自带的Kerberos库足够支撑这套流程。
二、配置Mac端的Kerberos环境
- 编辑
/etc/krb5.conf文件,把你的Windows域信息填进去:
[libdefaults] default_realm = YOUR_DOMAIN.COM # 大写,比如你的域是example.com就写EXAMPLE.COM dns_lookup_kdc = true dns_lookup_realm = true ticket_lifetime = 24h renew_lifetime = 7d [realms] YOUR_DOMAIN.COM = { kdc = dc.your_domain.com # 域控制器的主机名或IP admin_server = dc.your_domain.com default_domain = your_domain.com } [domain_realm] .your_domain.com = YOUR_DOMAIN.COM your_domain.com = YOUR_DOMAIN.COM
- 测试Kerberos是否能正常获取票据:在Mac终端敲
kinit your-domain-user@YOUR_DOMAIN.COM,输入该用户的域密码,如果没报错,再敲klist能看到票据信息,就说明配置没问题了。
三、为Java Web应用配置SPNEGO认证
这里分两种常见场景来说,你可以对应自己的应用类型来选:
场景1:Spring Boot应用(最主流)
1. 添加依赖
在pom.xml里加Spring Security Kerberos的支持:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-kerberos-web</artifactId> <version>1.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-kerberos-core</artifactId> <version>1.0.1.RELEASE</version> </dependency>
2. 配置Spring Security
写一个SecurityConfig类,把Kerberos认证和你的OpenLDAP验证串起来:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { // 从配置文件读取Kerberos参数 @Value("${kerberos.service-principal}") private String servicePrincipal; @Value("${kerberos.keytab-path}") private String keytabPath; // 自定义LDAP用户映射,把OpenLDAP的用户属性转成Spring Security的UserDetails @Autowired private LdapUserDetailsContextMapper userDetailsMapper; @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() // SPNEGO的认证入口,当浏览器没有Kerberos票据时返回401触发协商 .exceptionHandling() .authenticationEntryPoint(new SpnegoEntryPoint()) .and() // 添加SPNEGO认证过滤器 .addFilterBefore(spnegoAuthFilter(), BasicAuthenticationFilter.class); } @Bean public SpnegoAuthenticationProcessingFilter spnegoAuthFilter() throws Exception { SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter(); filter.setAuthenticationManager(authenticationManagerBean()); return filter; } @Override public AuthenticationManager authenticationManagerBean() throws Exception { // 同时启用Kerberos认证和LDAP用户验证 return new ProviderManager(Arrays.asList(kerberosAuthProvider(), ldapAuthProvider())); } // Kerberos认证提供者:验证票据的合法性 @Bean public KerberosAuthenticationProvider kerberosAuthProvider() { KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider(); provider.setKerberosAuthentication(new KerberosAuthentication(servicePrincipal, keytabPath)); // 票据验证通过后,去LDAP拉取用户详情 provider.setUserDetailsService(ldapUserDetailsService()); return provider; } // LDAP认证提供者:关联你的本地OpenLDAP @Bean public LdapAuthenticationProvider ldapAuthProvider() { BindAuthenticator authenticator = new BindAuthenticator(ldapContextSource()); // 这里要匹配你OpenLDAP的用户DN格式,比如我的用户都在ou=users下,就是uid={0},ou=users,dc=myopenldap,dc=com authenticator.setUserDnPatterns(new String[]{"uid={0},ou=users,dc=your-openldap-domain,dc=com"}); return new LdapAuthenticationProvider(authenticator, userDetailsMapper); } @Bean public DefaultSpringSecurityContextSource ldapContextSource() { // 你的OpenLDAP连接地址,比如ldap://localhost:389/ou=users,dc=myopenldap,dc=com return new DefaultSpringSecurityContextSource("ldap://localhost:your-openldap-port/ou=users,dc=your-openldap-domain,dc=com"); } @Bean public LdapUserDetailsService ldapUserDetailsService() { LdapUserDetailsService service = new LdapUserDetailsService(ldapContextSource()); service.setUserDetailsContextMapper(userDetailsMapper); return service; } }
3. 配置文件参数补充
在application.properties里加这些参数:
# Kerberos相关 kerberos.service-principal=HTTP/your-mac-hostname.your-domain.com@YOUR_DOMAIN.COM kerberos.keytab-path=/etc/krb5.keytab # OpenLDAP相关(如果需要绑定认证的话) spring.ldap.username=cn=admin,dc=your-openldap-domain,dc=com spring.ldap.password=your-openldap-admin-password
场景2:传统Java EE/Tomcat应用
如果是部署在Tomcat上的传统应用,可以这样搞:
- 在Tomcat的
server.xml里配置OpenLDAP Realm,用来关联用户信息。 - 添加SPNEGO Valve到
context.xml,开启HTTP层面的Kerberos协商。 - 编写一个简单的过滤器,把SPNEGO认证后的用户名传递给应用的权限系统。
核心逻辑和Spring Boot一致:先通过Kerberos验证域身份,再去OpenLDAP拉取用户权限。
四、在Windows域控制器上注册SPN和生成Keytab
这步是让Java应用能和域控制器互信的核心:
- 用域管理员账号登录域控制器,打开命令提示符:
- 注册服务主体名称(SPN):
setspn -A HTTP/your-mac-hostname.your-domain.com YOUR_DOMAIN\service-account
这里的service-account是域内的一个服务账号(可以新建一个专门用来跑Java应用的账号),your-mac-hostname.your-domain.com是Mac机器的完整域名(要能被域内机器解析)。 - 生成Keytab文件:
ktpass /out krb5.keytab /princ HTTP/your-mac-hostname.your-domain.com@YOUR_DOMAIN.COM /mapuser YOUR_DOMAIN\service-account /pass * /ptype KRB5_NT_PRINCIPAL
执行后输入服务账号的密码,就会生成krb5.keytab文件。
- 注册服务主体名称(SPN):
- 把生成的
krb5.keytab复制到Mac机器的/etc/目录下,然后设置权限:sudo chmod 600 /etc/krb5.keytab(只有root能读写,避免泄露)。
五、测试SSO效果
- 在Windows域内的机器上打开浏览器(Chrome/Edge/IE都可以):
- Chrome需要配置信任域名:在
chrome://flags/#auth-server-whitelist里添加your-mac-hostname.your-domain.com。 - IE/Edge可以直接把应用地址加入“本地Intranet”站点。
- Chrome需要配置信任域名:在
- 访问你的Java Web应用,应该直接跳转到登录后的页面,不需要输入用户名密码。
- 如果遇到问题,可以看应用的日志,或者在Mac终端用
klist查看应用是否获取到了Kerberos票据,也可以检查域控制器的事件日志。
几个注意点
- 时间同步:Kerberos对时间差很敏感,Mac机器和域控制器的时间差不能超过5分钟,一定要同步好(可以用NTP服务)。
- 用户同步:如果你的OpenLDAP和AD是独立的,要确保用户信息一致,比如用户名、邮箱等,可以用LDAP同步工具定期同步。
- 防火墙:确保Mac机器和域控制器之间的Kerberos端口(88/UDP、464/TCP)是通的。
内容的提问来源于stack exchange,提问作者BK201
相关产品推荐
相关产品推荐

