使用Spring Security 4.2与Tomcat 8.5登录成功后未创建会话问题
嘿,我来帮你排查下这个登录后没会话、一直是ROLE_ANONYMOUS的问题,大概率是这几个地方出了岔子:
会话管理配置误设为无状态
要是你在Spring Security配置里不小心加了sessionCreationPolicy(SessionCreationPolicy.STATELESS),那系统会彻底禁用会话,不管登录成功与否都只会返回匿名角色。赶紧检查下配置,改成按需创建会话:@Override protected void configure(HttpSecurity http) throws Exception { http // 其他配置项... .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); // 或者根据需求用ALWAYS }表单登录的路径配置不匹配
登录页面的表单action必须和Spring Security配置里的loginProcessingUrl完全一致,不然请求根本不会被认证过滤器处理,自然不会生成会话。比如你的表单action是/login-action,那配置得这么写:http .formLogin() .loginPage("/login") // 你的登录页面地址 .loginProcessingUrl("/login-action") // 和表单action对应 .defaultSuccessUrl("/success") // 登录成功跳转的URL .permitAll();XML认证配置存在语法错误
你贴的XML配置没写完,<security:authentication-provider>标签都没闭合,这会导致整个认证管理器加载失败,相当于没启用认证逻辑。完整的正确配置应该是这样:<security:authentication-manager> <security:authentication-provider> <security:user-service> <security:user disabled="false" locked="false" name="user" password="pass" authorities="USER,ROLE_USER,SUPERUSER"/> </security:user-service> </security:authentication-provider> </security:authentication-manager>另外注意!Spring Security 5+要求密码必须加密存储,明文密码会直接导致认证失败(哪怕页面跳了,实际没通过认证)。你得加个密码编码器:
<security:authentication-manager> <security:authentication-provider> <security:password-encoder ref="bcryptPasswordEncoder"/> <security:user-service> <!-- 这里的密码是BCrypt加密后的字符串,比如你可以用BCryptPasswordEncoder.encode("pass")生成 --> <security:user disabled="false" locked="false" name="user" password="$2a$10$xxxxxx..." authorities="USER,ROLE_USER,SUPERUSER"/> </security:user-service> </security:authentication-provider> </security:authentication-manager> <bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>CSRF令牌缺失导致认证被拦截
默认情况下Spring Security开启了CSRF保护,要是你的登录表单没提交CSRF令牌,系统会偷偷拒绝登录请求。赶紧在表单里加个隐藏域:<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>要是测试环境嫌麻烦,可以临时关闭CSRF(生产环境绝对别这么干):
http.csrf().disable();开启调试日志排查细节
要是上面的方法都没用,就开Spring Security的调试日志,看看认证流程到底哪一步出问题了:logging.level.org.springframework.security=DEBUG从日志里能看到请求有没有进入认证流程、认证对象有没有生成、会话是否被创建,一查一个准。
内容的提问来源于stack exchange,提问作者D Smith

