Spring Security登出异常:JSESSIONID变更后仍可访问受限路径
解决Spring Security登出后仍能访问受限路径的问题
兄弟,我一眼就瞅到问题所在了——你用的是HttpBasic认证,这玩意儿有个容易踩的坑:浏览器会自动缓存你的用户名密码凭证,就算你销毁了会话、删除了Cookie,下次发送请求时浏览器还是会偷偷把Authorization请求头带上,服务器直接就给你重新完成认证了,自然能继续访问那些本该受限的路径!
咱们来拆解下你的配置和问题根源:
问题核心原因
HttpBasic认证的机制是让浏览器将用户名密码以Base64编码后放在Authorization头中发送给服务器,大部分浏览器会默认缓存这个凭证,除非收到服务器返回的WWW-Authenticate响应头,否则会在后续同域名的请求中自动带上这个头。你当前的登出配置只是销毁了会话、删除了Cookie,但并没有告诉浏览器要清除缓存的凭证,所以浏览器还是会帮你自动“登录”。
解决方案
根据你的使用场景,有两种可行的修复方式:
方案1:改用表单登录(推荐)
如果你的场景是普通的Web应用,建议放弃HttpBasic,改用Spring Security的表单登录,这种方式浏览器不会缓存登录凭证,登出后会话失效就必须重新登录:
public void configure(HttpSecurity httpSecurity) throws Exception{ httpSecurity // 替换HttpBasic为表单登录 .formLogin() .and() .authorizeRequests() .mvcMatchers(HttpMethod.GET, "/privateEvent").hasAuthority("REGISTERED_USER") .mvcMatchers(HttpMethod.DELETE, "/privateEvent/*").hasAuthority("RSVP_ADMIN") .mvcMatchers("/registerPrivateEvent").hasAuthority("REGISTERED_USER") .mvcMatchers("/guestList").hasAuthority("EVENT_PUBLISHER") .mvcMatchers("/eventPublishersList").hasAuthority("RSVP_ADMIN") .anyRequest().permitAll() .and() .logout() .invalidateHttpSession(true) // 合并deleteCookies调用,更简洁 .deleteCookies("JSESSIONID", "XSRF-TOKEN") .clearAuthentication(true) .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/allDone") .permitAll() .and() // 表单登录建议开启CSRF防护,这里保留你原有的配置,可根据需求调整 .csrf().disable(); }
方案2:保留HttpBasic,强制浏览器清除凭证
如果你必须使用HttpBasic认证,可以通过自定义LogoutSuccessHandler,在登出成功时返回WWW-Authenticate响应头,强制浏览器清除缓存的凭证:
public void configure(HttpSecurity httpSecurity) throws Exception{ httpSecurity .httpBasic() .and() .authorizeRequests() .mvcMatchers(HttpMethod.GET, "/privateEvent").hasAuthority("REGISTERED_USER") .mvcMatchers(HttpMethod.DELETE, "/privateEvent/*").hasAuthority("RSVP_ADMIN") .mvcMatchers("/registerPrivateEvent").hasAuthority("REGISTERED_USER") .mvcMatchers("/guestList").hasAuthority("EVENT_PUBLISHER") .mvcMatchers("/eventPublishersList").hasAuthority("RSVP_ADMIN") .anyRequest().permitAll() .and() .logout() .invalidateHttpSession(true) .deleteCookies("JSESSIONID", "XSRF-TOKEN") .clearAuthentication(true) .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) // 自定义登出成功处理器,添加强制清除凭证的响应头 .logoutSuccessHandler((request, response, authentication) -> { response.addHeader("WWW-Authenticate", "Basic realm=\"YourApplicationRealm\""); response.sendRedirect("/allDone"); }) .permitAll() .and() .csrf().disable(); }
额外小优化
你的配置中多次调用deleteCookies,可以合并成一次调用,代码会更简洁哦~
内容的提问来源于stack exchange,提问作者Anna Nichols
相关产品推荐
相关产品推荐

