Spring Security表单登录失效求助:自定义登录页跳转异常
嘿,我刚帮你梳理了这个问题的常见原因和解决办法,你遇到的情况其实挺典型的——当你给/login路径设置security="none"后,虽然能看到自定义登录页,但Spring Security的过滤器链没处理这个路径的登录请求,或者表单提交的参数、CSRF配置有问题,导致认证失败跳回登录页。下面一步步来排查和解决:
security="none" 你之前的配置里,把/login设为security="none",但这个路径其实是Spring Security处理登录请求的默认路径!一旦设置了security="none",Spring Security的UsernamePasswordAuthenticationFilter就会跳过这个路径,根本不会处理你的登录提交请求,自然会因为认证失败跳回登录页。
正确的做法是把自定义登录页的访问路径和登录请求处理路径分开:
- 比如把登录页的路径设为
/login-page,给这个路径放行(permitAll或者security="none") - 登录表单的提交
action指向默认的/login(或者你在<form-login>里配置的login-processing-url),这个路径要让Spring Security过滤器处理,不能设security="none"
给你个spring-security.xml的配置示例:
<http> <!-- 放行自定义登录页的访问路径 --> <intercept-url pattern="/login-page" access="permitAll"/> <!-- 其他需要保护的业务路径 --> <intercept-url pattern="/**" access="hasRole('USER')"/> <!-- 配置自定义登录页和登录处理规则 --> <form-login login-page="/login-page" login-processing-url="/login" <!-- 这个路径不能设security="none" --> default-target-url="/home" authentication-failure-url="/login-page?error"/> </http>
对应的登录表单(比如login-page.jsp)要这么写,注意参数名和CSRF令牌:
<form action="${pageContext.request.contextPath}/login" method="post"> <div> <label>用户名: <input type="text" name="username"/></label> </div> <div> <label>密码: <input type="password" name="password"/></label> </div> <div> <input type="submit" value="登录"/> </div> <!-- Spring Security 4默认开启CSRF保护,必须携带这个令牌 --> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> </form>
Spring Security 4.x默认是开启CSRF保护的,如果你的登录表单里没加上面的CSRF隐藏域,Spring Security会直接拒绝登录请求,这也是跳回登录页的常见原因。
如果是测试环境想临时跳过CSRF(生产环境不推荐),可以在spring-security.xml里关闭:
<http> <!-- 其他配置 --> <csrf disabled="true"/> </http>
确保Spring Security的过滤器拦截了所有请求,这样才能处理登录请求。web.xml里的配置应该类似:
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
如果上面的配置都没问题,那可能是你的UserDetailsService或者认证提供者的逻辑有问题,导致正确凭据也认证失败。可以开启Spring Security的DEBUG日志排查:
比如在logback配置里加:
<logger name="org.springframework.security" level="DEBUG"/>
然后看日志里的认证过程,找Authentication success或Authentication failed的日志信息,定位具体失败原因。
内容的提问来源于stack exchange,提问作者Arjs

