背景
我在应用程序方面遇到了一些问题。我们使用Spring Boot 2.4.10和Spring Security 5.4.8,使用cookie与应用程序进行交互。
我们在src/main/resources
中存储了一个前端应用程序,其中包括连接到在/api/v1/notification
中公开的websocket端点的功能。
我的配置
application.properties
文件:
# cookie-related settings
server.servlet.session.cookie.name=mySessionCookie
server.servlet.session.cookie.path=/
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final String[] authorizedWithoutAuth = {
"/",
"/index.html",
"/static/**"
};
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers(authorizedWithoutAuth).permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.and()
.logout().logoutUrl("/api/v1/logout").invalidateHttpSession(true)
.deleteCookies("mySessionCookie");
}
}
问题
在没有用户登录时,前端会定期尝试到达WebSocket终端点以打开连接。
第一次api/v1/notification
结束时,将重定向到/error
端点,该端点返回一个带有'Set-Cookie'标头(我认为这可能是在第一次请求中设置的匿名Cookie?)和401状态的HttpServletResponse
。 我无法更改此行为。
以下请求到api/v1/notification
使用此cookie在标题中(当用户未登录时)。 这些请求也被重定向到/error
端点,每次都返回带有401状态的HttpServletResponse
,但是此处不包括没有'Set-Cookie'标头。
一旦用户使用授权标头登录,响应会设置正确的Cookie,并在随后的请求中使用它。
问题是,有时设置的Cookie突然再次更改为无效的Cookie,随后使用此新的无效Cookie进行的下一个请求会转到登录页面。
检查代码后,似乎存在旧的api/v1/notification
请求(在登录请求之前)正在进行,其Cookie无效(即在登录之前存在的匿名Cookie)。
此请求被重定向到/error
端点:在这里,一次又一次地HttpServletResponse
都具有401状态,并且包含修改浏览器Cookie的Set-Cookie标头(替换好的Cookie)。
接下来是问题的图表,希望能更容易理解。
期望行为
我希望防止未经授权的请求设置会话Cookie。
如果先前的请求以401代码响应,则可以,但我不希望它更改当前设置的Cookie。
我尝试过...
I tried extending the
ErrorController
by returning aResponseEntity
with all the headers present in the inputHttpServletResponse
except for the 'Set-Cookie' header. This doesn't work.I also tried modifying my configuration to disable anonymous requests:
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final String[] authorizedWithoutAuth = { "/", "/index.html", "/static/**" }; @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic() .and() .anonymous().disable() .authorizeRequests() // .antMatchers(authorizedWithoutAuth).permitAll() I had to remove these from here, and include them in the method below .anyRequest().authenticated() .and() .csrf().disable() .and() .logout().logoutUrl("/api/v1/logout").invalidateHttpSession(true) .deleteCookies("mySessionCookie"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers(authorizedWithoutAuth); } }
but the session cookie is still set this way too, with 401 requests.
I also tried using
@ControllerAdvice
to handle the exceptions, but these are thrown by Spring Security in theAbstractSecurityInterceptor
, as learnt in this response.