我有一个基于SpringBoot的应用程序,有多个端点。由于将访问端点的不同客户端,我希望有不同的身份验证提供程序来保护它们。某些端点将受Kerberos(KerberosServiceAuthenticationProvider - http://docs.spring.io/autorepo/docs/spring-security-kerberos/1.0.0.RC1/reference/htmlsingle/)保护。某些端点将受AD / LDAP(ActiveDirectoryLdapAuthenticationProvider)保护。
我目前使用Kerberos或LDAP,但不能同时使用两者:
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected class ApplicationSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//For Kerberos
auth.authenticationProvider(kerberosAuthenticationProvider())
.authenticationProvider(kerberosServiceAuthenticationProvider());
//For LDAP
//auth.authenticationProvider(customAuthenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, APPLICATION_ADMIN_ENDPOINTS)
.permitAll()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.PUT, APPLICATION_ADMIN_ENDPOINTS)
.hasAnyAuthority(AUTHENTICATED_APPLICATION_ADMIN_AUTHORITIES)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.DELETE, APPLICATION_ADMIN_ENDPOINTS)
.hasAnyAuthority(AUTHENTICATED_APPLICATION_ADMIN_AUTHORITIES)
.and()
.authorizeRequests()
.antMatchers(CLIENT_ENDPOINTS)
.permitAll()
.and()
.authorizeRequests()
.antMatchers(SWAGGER_ENDPOINTS)
.permitAll()
.and()
.authorizeRequests()
.antMatchers(MANAGER_ENDPOINTS)
.hasAnyAuthority(AUTHENTICATED_MANAGER_AUTHORITIES)
.and()
.authorizeRequests()
.antMatchers(TRUSTED_AGENT_ENDPOINTS)
.hasAnyAuthority(AUTHENTICATED_TRUSTED_AGENT_AUTHORITIES)
.and()
.authorizeRequests()
.antMatchers("/kerb/**")
.hasAnyAuthority(AUTHENTICATED_APPLICATION_ADMIN_AUTHORITIES)
.and()
.addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), BasicAuthenticationFilter.class)
.httpBasic()
.and()
.csrf()
.disable();
}
}
@Bean
public AuthenticationProvider customAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
ldapDomain, ldapUrl);
SimpleCaseAndWhitespaceMitigatingAuthoritiesMapper authoritiesMapper = new SimpleCaseAndWhitespaceMitigatingAuthoritiesMapper();
provider.setAuthoritiesMapper(authoritiesMapper);
provider.setConvertSubErrorCodesToExceptions(true);
return provider;
}
@Bean
public KerberosAuthenticationProvider kerberosAuthenticationProvider() {
KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider();
SunJaasKerberosClient client = new SunJaasKerberosClient();
client.setDebug(true);
provider.setKerberosClient(client);
provider.setUserDetailsService(kerberosUserService());
return provider;
}
@Bean
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();
provider.setTicketValidator(sunJaasKerberosTicketValidator());
provider.setUserDetailsService(kerberosUserService());
return provider;
}
@Bean
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
ticketValidator.setServicePrincipal(kerberosPrincipal);
File f = new File(keytabFile);
try {
LOG.info(String.format("Absolute: %s, Canonical: %s", f.getAbsolutePath(), f.getCanonicalPath()));
if(f.exists()){
LOG.info("File exists.");
}
else{
LOG.info("File DOES NOT exist.");
}
} catch (IOException e) {
e.printStackTrace();
}
ticketValidator.setKeyTabLocation(new FileSystemResource(f));
ticketValidator.setDebug(true);
return ticketValidator;
}
@Bean
public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();
filter.setAuthenticationManager(authenticationManager);
return filter;
}
@Bean
public KerberosUserDetailsService kerberosUserService() {
return new KerberosUserDetailsService();
}
无论如何要让两者兼顾?我正在考虑制作一个可以处理请求的自定义身份验证提供程序,但不确定这是否有用。
答案 0 :(得分:0)
最容易想到的是基于url映射必须在Web.xml中使用SpringDistpatcherServlets。然后,每个URL映射都在不同的spring上下文中。然后,每个spring上下文都有自己的安全性。
答案 1 :(得分:0)
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(kerberosAuthenticationProvider());
auth.authenticationProvider(kerberosServiceAuthenticationProvider());
auth.authenticationProvider(customAuthenticationProvider());
}
答案 2 :(得分:0)
您正在做的是将Kerberos的authenticationProviders
和您的自定义变量都添加到AuthenticationManagerBuilder
中。这应该注册所有这些人。
运行时会发生什么:
有一个ProviderManager
处理您所有已注册的AuthenticationProvider
和内建版本。
permitAll
,那么故事就此结束ProviderManager
按照您提供的顺序遍历所有AuthenticationProvider
。它检查它们是否支持身份验证,并尝试对其进行身份验证。如果失败,则移至下一个(如果有则保存例外)DaoAuthenticationProvider
处理正常的用户名-密码凭证 结论:
即使不是您想要的,您所做的工作也应该非常接近。对于受Kerberos保护的端点,它将使用kerberos AuthenticationProvider
。对于其他端点,它将尝试使Kerberos失败并继续使用自定义提供程序。
如果仍然无法正常工作,我建议在类org.springframework.security.authentication.ProviderManager
中设置一个断点,并查看断点如何处理您的提供程序。