我是 Spring Boot 新手,我尝试将 Spring Boot 安全性与 kerberos 集成,以便我可以实现 sso 并在我的应用程序中获取 Windows 用户信息。 由于我的 Windows 用户凭证存储在内存中(我相信我不需要设置 krb5.conf 和 jaas.conf),到目前为止我所做的只是更新我的 pom.xml 和 securityconfiguration.java:
pom.xml:
<dependencies>
<!-- Spring Boot Starter Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Security Kerberos -->
<dependency>
<groupId>org.springframework.security.kerberos</groupId>
<artifactId>spring-security-kerberos-core</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>
<!-- Thymeleaf for HTML templates -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
安全配置.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider;
import org.springframework.security.kerberos.client.sun.SunJaasKerberosTicketValidator;
import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter;
import org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests.anyRequest().authenticated()
)
.exceptionHandling(exceptionHandling ->
exceptionHandling.authenticationEntryPoint(spnegoEntryPoint())
)
.addFilterBefore(spnegoAuthenticationProcessingFilter(), BasicAuthenticationFilter.class);
return http.build();
}
@Bean
public SpnegoEntryPoint spnegoEntryPoint() {
return new SpnegoEntryPoint();
}
@Bean
public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter() throws Exception {
SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();
filter.setAuthenticationManager(authenticationManager());
return filter;
}
@Bean
public AuthenticationManager authenticationManager() {
List<org.springframework.security.authentication.AuthenticationProvider> providers = new ArrayList<>();
providers.add(kerberosServiceAuthenticationProvider());
return new ProviderManager(providers);
}
@Bean
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();
provider.setTicketValidator(sunJaasKerberosTicketValidator());
provider.setUserDetailsService(userDetailsService());
return provider;
}
@Bean
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
// Do not set a service provider to leverage the Windows ticket cache
// Do not set a keytab location to leverage the Windows ticket cache
ticketValidator.setDebug(true);
return ticketValidator;
}
@Bean
public UserDetailsService userDetailsService() {
return username -> {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(username, "", authorities);
};
}
}
但是,当我尝试启动我的应用程序时,它仍然表示必须指定服务主体和密钥选项卡。 调试日志显示 useTicketCache=false,但我在 jaas.conf 中明确将其设置为 true 并将其添加到 eclipse 中的运行配置中: jaas.conf:
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=true
doNotPrompt=true
renewTGT=true;
};
设置jaas.conf路径:
String jaasConfigPath = "C:\\path\\to\\your\\jaas.conf";
System.setProperty("java.security.auth.login.config", jaasConfigPath);
如果我缺少任何内容,请告诉我,或者如何告诉应用程序我正在尝试从内存缓存获取用户信息,我使用 Windows 10、Java 21、Spring Boot 3.3.2 和 Eclipse。 谢谢你的帮助
有些事情你完全倒退了。
我没有关键选项卡位置,因为当我使用 klist 时,我看到 4 或 5 个条目,它们都没有指定关键缓存位置,我假设它存储在内存中
是的,但是它们位于客户端的内存中,并且您的Web应用程序的Java代码不在客户端系统上运行,因此它无法看到客户端的内存或客户端的票证缓存。因此从客户端命令查找服务器端位置是没有意义的。
(即使 web 应用程序此时碰巧在“localhost”上运行,这仍然是正确的 – Java 代码和浏览器仍然是仅通过 HTTP 通信的独立实体,并且 web 应用程序无论如何都无法自动查看客户端的缓存票证。当然,一旦部署,它将完全在不同的机器上。)
其次,您在
klist
中看到的不是密钥表。 不要将票证缓存与密钥表混淆——在某种程度上,它们是完全相反的东西;一般来说,票证缓存保存用户的登录凭据,而密钥表保存服务器的凭据。 keytab 有点像 SSL 证书。
(当然,也有例外 - 有时服务充当客户端并具有票证缓存,有时客户端具有密钥表,但希望这不会太混淆要点。)
但是,当我尝试启动我的应用程序时,它仍然表示必须指定服务主体和密钥选项卡。调试日志显示 useTicketCache=false,但我在 jaas.conf 中明确将其设置为 true 并将其添加到 eclipse 中的运行配置中: jaas.conf:
useTicketCache 是无关紧要的,因为 Kerberos 服务没有票证缓存(或与此相关的 TGT)——只有客户端拥有这些东西。
(此设置仅适用于 Java Web 应用程序本身充当其他基于 Kerberos 的系统的客户端的情况(例如与 API 或 LDAP 通信)。稍后您可能需要它,但不适用于此特定任务。)
再次强调,不要将票证缓存与密钥表混淆。服务器没有票证缓存,但它需要一个密钥表——您必须发布一个密钥表,并且必须在服务器的配置中指定一个密钥表。客户端上运行的浏览器将访问其票证缓存并通过网络将票证发送到您的 Web 应用程序,并且 Web 应用程序将根据其密钥表对其进行验证。