Spring Security认证后SecurityContextHolder返回AnonymousUser问题求助
问题原因及解决方案
核心原因
- 无状态会话配置冲突:你在
WebSecurityConfig中设置了sessionCreationPolicy(SessionCreationPolicy.STATELESS),但表单登录机制依赖HTTP会话存储用户认证状态。无状态模式下,Spring Security不会创建或维护会话,登录成功后的认证信息无法在后续请求中保留,跳转后SecurityContextHolder只能获取到匿名用户。 - 权限规则过于宽松:
authorizeHttpRequests中配置了anyRequest().permitAll(),意味着所有请求都允许匿名访问,即使用户已登录,后续请求也不会触发认证信息的加载与校验,进一步导致认证状态丢失。
解决步骤
1. 调整会话策略
将会话创建策略改为默认的IF_REQUIRED(或直接移除该配置,Spring Security默认即为此策略),让框架在需要时创建会话保存认证状态:
.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
2. 修正权限规则
将需要认证的请求设置为authenticated(),确保登录后的请求会校验认证状态:
protected AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry buildRequests(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry requests) { return requests.requestMatchers(possiblePatterns) .permitAll() .anyRequest() .authenticated(); // 替换permitAll为authenticated }
3. 额外注意事项
- 登录表单需包含CSRF令牌:Thymeleaf模板中使用
th:action可自动生成,或手动添加<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>,避免CSRF校验失败导致认证异常。 - 生产环境需替换密码明文处理:
JpaUserDetailsService中的{noop}前缀仅用于测试,正式环境要使用BCrypt等加密算法存储密码。
修改后的WebSecurityConfig关键代码
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(this::buildRequests) .formLogin(this::formCustomizer) .logout(LogoutConfigurer::permitAll) .userDetailsService(userDetailsService) .httpBasic() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); return http.build(); } protected AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry buildRequests(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry requests) { return requests.requestMatchers(possiblePatterns) .permitAll() .anyRequest() .authenticated(); }
内容的提问来源于stack exchange,提问作者Helen Barskaya
相关产品推荐
相关产品推荐

