同一路径回退到 SAML2 的 JWT 身份验证
JWT authentication with fallback to SAML2 for the same path
我在我的 spring 启动应用程序之一中使用 spring-security-saml2-service-provider
进行身份验证,并且我使用自定义 JwtAuthorizationFilter
(通过 http 身份验证 header)在不同的 spring 启动应用程序中。
它们都可以完美地独立工作。
现在我需要编写一个 spring 启动应用程序来使用它们。如果 JWT 令牌可用(身份验证 header),则使用 JwtAuthorizationFilter
,否则使用 saml2Login
.
SAML2 配置如下所示:(无过滤器,只有 saml2Login
)
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/saml2/service-provider-metadata/**").permitAll()
.antMatchers("/**").authenticated().and()
// use SAML2
.saml2Login()
.addObjectPostProcessor(new ObjectPostProcessor<OpenSamlAuthenticationProvider>() {
public <O extends OpenSamlAuthenticationProvider> O postProcess(O samlAuthProvider) {
samlAuthProvider.setAuthoritiesExtractor(authoritiesExtractor());
samlAuthProvider.setAuthoritiesMapper(authoritiesMapper());
return samlAuthProvider;
}
})
;
}
JWT 配置如下所示:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/**").authenticated().and()
// use JWT
.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUtil))
;
}
我想我需要类似 JwtOrSaml2AuthenticationFilter
的东西,但不知道该怎么做。
解决方法是
- 使用@Order 和
复制配置
在addFilter
之前设置一个基于header的requestMatcher
@EnableWebSecurity
public class SecurityConfiguration {
@Order(100) // lower number = higher priority
@Configuration
@RequiredArgsConstructor
public static class AppSecurityJWT extends WebSecurityConfigurerAdapter {
final JWTUtil jwtUtil;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/saml2/service-provider-metadata/**", "/idm-app/**").permitAll()
.antMatchers("/**").authenticated().and()
// This configuration will only be active if the Authorization header is present in the request
.requestMatcher(new RequestHeaderRequestMatcher("Authorization")).addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUtil))
;
}
}
@Order(101)
@Configuration
@RequiredArgsConstructor
public static class AppSecuritySAML2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/saml2/service-provider-metadata/**", "/idm-app/**").permitAll()
.antMatchers("/**").authenticated().and()
// This whole configuration will only be active, if the previous (100) didn't match
.saml2Login()
//...
;
}
}
我在我的 spring 启动应用程序之一中使用 spring-security-saml2-service-provider
进行身份验证,并且我使用自定义 JwtAuthorizationFilter
(通过 http 身份验证 header)在不同的 spring 启动应用程序中。
它们都可以完美地独立工作。
现在我需要编写一个 spring 启动应用程序来使用它们。如果 JWT 令牌可用(身份验证 header),则使用 JwtAuthorizationFilter
,否则使用 saml2Login
.
SAML2 配置如下所示:(无过滤器,只有 saml2Login
)
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/saml2/service-provider-metadata/**").permitAll()
.antMatchers("/**").authenticated().and()
// use SAML2
.saml2Login()
.addObjectPostProcessor(new ObjectPostProcessor<OpenSamlAuthenticationProvider>() {
public <O extends OpenSamlAuthenticationProvider> O postProcess(O samlAuthProvider) {
samlAuthProvider.setAuthoritiesExtractor(authoritiesExtractor());
samlAuthProvider.setAuthoritiesMapper(authoritiesMapper());
return samlAuthProvider;
}
})
;
}
JWT 配置如下所示:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/**").authenticated().and()
// use JWT
.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUtil))
;
}
我想我需要类似 JwtOrSaml2AuthenticationFilter
的东西,但不知道该怎么做。
解决方法是
- 使用@Order 和 复制配置
在addFilter
之前设置一个基于header的requestMatcher@EnableWebSecurity public class SecurityConfiguration { @Order(100) // lower number = higher priority @Configuration @RequiredArgsConstructor public static class AppSecurityJWT extends WebSecurityConfigurerAdapter { final JWTUtil jwtUtil; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and() .antMatcher("/**").authorizeRequests() .antMatchers("/saml2/service-provider-metadata/**", "/idm-app/**").permitAll() .antMatchers("/**").authenticated().and() // This configuration will only be active if the Authorization header is present in the request .requestMatcher(new RequestHeaderRequestMatcher("Authorization")).addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUtil)) ; } } @Order(101) @Configuration @RequiredArgsConstructor public static class AppSecuritySAML2 extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and() .antMatcher("/**").authorizeRequests() .antMatchers("/saml2/service-provider-metadata/**", "/idm-app/**").permitAll() .antMatchers("/**").authenticated().and() // This whole configuration will only be active, if the previous (100) didn't match .saml2Login() //... ; } }