升级至Spring Security 4后登录功能异常问题求助
从你的配置和描述来看,有几个关键问题可能导致登录后重定向回登录页,以下是逐一排查和解决的方案:
1. CSRF防护默认开启导致请求被拦截(最可能的原因)
Spring Security 4 默认启用了CSRF保护机制,而你的登录表单中并没有包含CSRF令牌字段。这会导致登录的POST请求被Spring Security视为无效请求,直接拦截并重定向回登录页面,而且通常不会在日志中输出明显错误(除非开启了更详细的调试日志)。
解决方法:
在登录表单中添加CSRF令牌隐藏字段:
<form class="form-signin" action='<spring:url value="/j_spring_security_check" />' method="POST"> <!-- 原有表单内容 --> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <!-- 提交按钮等 --> </form>
如果你的应用是纯后端服务(没有前端页面提交表单的场景),也可以临时关闭CSRF保护(不推荐生产环境使用):
<http> <!-- 其他配置项 --> <csrf disabled="true"/> </http>
2. AuthenticationManager配置错误
你的Spring Security 4配置中,手动定义ProviderManager时犯了一个小错误:在构造参数里重新创建了一个DaoAuthenticationProvider实例,而不是引用已经定义好的daoAuthenticationProvider bean。这会导致实际使用的认证提供者不是你配置的那个,可能引发认证失败。
修正后的ProviderManager配置:
<beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager"> <beans:constructor-arg> <beans:list> <beans:ref local="daoAuthenticationProvider" /> </beans:list> </beans:constructor-arg> </beans:bean>
另外,建议统一你的认证管理器配置方式:要么手动定义ProviderManager,要么使用<authentication-manager>简化配置(推荐后者):
<authentication-manager> <authentication-provider ref="daoAuthenticationProvider"/> </authentication-manager>
使用这种方式时,不需要手动创建ProviderManager,Spring会自动帮你生成对应的bean。
3. 登录参数的兼容性优化(非紧急但推荐)
虽然Spring Security 4仍兼容j_username和j_password这两个旧参数名,但官方推荐使用标准的username和password。你可以修改表单和配置来适配:
- 修改登录表单的输入字段name属性:
<input type="text" class="input-block-level loginTextInput" placeholder="Username" name="username" id="username" autofocus="autofocus" > <input type="password" class="input-block-level loginTextInput" placeholder="Password" name="password" id="password">
- 在Spring Security配置中明确指定参数名(如果需要):
<http> <form-login login-page="/login" username-parameter="username" password-parameter="password"/> </http>
先尝试解决第一个CSRF的问题,这通常是升级后出现该现象的最主要原因。如果问题仍存在,再检查认证管理器的配置。
内容的提问来源于stack exchange,提问作者jsmos

