在使用spring session的spring boot项目中,如何针对不同的URL配置两种 session 管理策略?
- 对于 Angular 前端,我想使用默认实现并创建
X-Auth-Token
token (如果需要,则创建 session ) - 但是对于公开的 API 端点,我想使用无状态 session 管理
我尝试了以下配置,但根本没有创建 session 。我认为第二个 block 正在覆盖 sessionCreationPolicy
因为它位于末尾
SecurityConfig.java
@Override
public void configure(HttpSecurity http) throws Exception
{
//Requests from angular app
http.authorizeRequests()
.antMatchers("/", "/login","/api/v1/user/login", "/api/v1/user/authenticate", "/api/v1/user/logout", "/api/v1/health/find/status").permitAll()
.antMatchers("/api/v1/person/**").hasAnyAuthority(ROLE_USER)
.and()
.httpBasic()
.and()
.exceptionHandling().authenticationEntryPoint(customBasicAuthenticationEntryPoint)
.and()
.logout()
.invalidateHttpSession(true).clearAuthentication(true)
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
//Requests from external systems
http.authorizeRequests()
.antMatchers("/api/v1/external/**").hasAnyAuthority(ROLE_API_USER)
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
更新
为 API 端点和 Angular 应用程序添加了自定义 WebSecurity 配置器适配器,如下所示。添加此后,API端点不会创建 session ,但Angular HTTP请求也不会创建 session
@Configuration
@EnableWebSecurity
public class SecurityConfig
{
....
@Configuration
@Order(1)
public class ExternalApiSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
{
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider()).eraseCredentials(true);
}
@Override
public void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.antMatchers("/api/v1/search/**").hasAnyAuthority(ROLE_API_USER, ROLE_SYS_ADMIN)
.and()
.httpBasic()
.and()
.exceptionHandling().authenticationEntryPoint(customBasicAuthenticationEntryPoint)
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.headers()
.frameOptions().disable();
// Uses CorsConfigurationSource bean defined below
http.cors().configurationSource(corsConfigurationSource());
http.csrf().disable();
}
}
@Configuration
@Order(2)
public class DefaultSecurityConfig extends WebSecurityConfigurerAdapter
{
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
@Override
public void configure(WebSecurity webSecurity)
{
webSecurity.ignoring().antMatchers("/static/**");
}
@Override
public void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.antMatchers("/", "/login","/api/v1/user/login", "/api/v1/user/authenticate", "/api/v1/user/logout", "/api/v1/health/find/status").permitAll()
.antMatchers("/api/v1/person/**").hasAnyAuthority(ROLE_USER)
.and()
.httpBasic()
.and()
.exceptionHandling().authenticationEntryPoint(customBasicAuthenticationEntryPoint)
.and()
.logout()
.invalidateHttpSession(true).clearAuthentication(true)
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
{
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider()).eraseCredentials(true);
auth.authenticationProvider(getDaoAuthenticationProvider()).eraseCredentials(true);
}
}
....
}
最佳答案
当您创建 WebSecurityConfigurerAdapter
时,您需要创建两个不同的过滤器链您正在创建一个包含所需安全 http 过滤器的代理过滤器链。
如果您查找DefaultSecurityFilterChain
,您应该能够在启动时看到这一点在日志中,您应该再次看到类似 Creating filter chain: any request, [Filters...]
的日志记录语句
DefaultSecurityFilterChain
默认情况下,任何请求( /**
)都会通过它。为了能够将请求分离到不同的过滤器链,您需要创建第二个 WebSecurityConfigurerAdapter
,将其范围限制为任何路径,并将您想要的配置应用到每个路径。
一个问题是您还需要对适配器应用更高的优先级,最终代码看起来像这样。
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
@Configuration
public static class ApiSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.antMatcher("/api/v1/external/**")
.authorizeRequests()
.anyRequest()
.hasAnyAuthority(ROLE_API_USER)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
@Order(Ordered.HIGHEST_PRECEDENCE + 2)
@Configuration
public static class DefaultSecurityFilter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
//Requests from angular app
http.authorizeRequests()
.antMatchers("/", "/login","/api/v1/user/login", "/api/v1/user/authenticate", "/api/v1/user/logout", "/api/v1/health/find/status").permitAll()
.antMatchers("/api/v1/person/**").hasAnyAuthority(ROLE_USER)
.and()
.httpBasic()
.and()
.exceptionHandling().authenticationEntryPoint(customBasicAuthenticationEntryPoint)
.and()
.logout()
.invalidateHttpSession(true).clearAuthentication(true)
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
}
在此之后您应该看到两个 DefaultSecurityFilterChain
在日志中创建,第一个是 "/api/v1/external/**"
第二个any request
捕获任何其他请求。
关于spring-boot - Spring session : How to create separate session management policies for different URLs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63262262/