自定义表单登录的Spring Security Filter失效,提交返回404
解决Spring Security自定义登录表单404及Filter未触发问题
嘿,我刚看完你的问题,这里有几个关键的地方出错了,咱们一步步来修复:
1. 自定义Filter的AuthenticationManager注入完全错了!
你在配置PasswordLoginFilter的时候,把authenticationProvider注入给了authenticationManager属性——这是核心错误!UsernamePasswordAuthenticationFilter需要的是AuthenticationManager实例,而不是AuthenticationProvider。
修正方法:
首先给你的authentication-manager标签加上id:
<authentication-manager id="authenticationManager"> <authentication-provider> <user-service> <user name="user1" password="test" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
然后修改Filter的注入配置:
<!-- 把ref="authenticationProvider"改成ref="authenticationManager" --> <beans:property ref="authenticationManager" name="authenticationManager" />
2. 同时用了自定义Filter和<form-login>标签,冲突了!
<form-login>会自动创建一个默认的UsernamePasswordAuthenticationFilter,而你又手动加了自定义Filter放在它前面,这就导致两个Filter抢着处理/login请求,你的自定义Filter自然不会被触发。
修正方法:
直接删掉配置里的<form-login>标签,因为你已经用自定义Filter处理登录逻辑了。
3. 路径配置错误导致404
你的路径配置有好几个问题:
login-page='/Webapp/login.jsp':Web应用的根路径是/,所以正确的登录页面路径应该是'/login.jsp'(假设login.jsp放在项目的webapp根目录下)。- 没有给
/login(登录提交路径)开匿名权限:用户提交登录请求时还没认证,Spring Security会拦截这个请求,导致404或者跳转错误。
修正后的intercept-url配置:
<http use-expressions="true"> <!-- 允许所有人访问登录页面和登录提交接口 --> <intercept-url pattern="/login.jsp" access="permitAll()" /> <intercept-url pattern="/login" access="permitAll()" /> <!-- 其他所有路径必须认证才能访问 --> <intercept-url pattern="/**" access="isAuthenticated()" /> <custom-filter ref="formAuthenticationFilter" before="FORM_LOGIN_FILTER"/> </http>
4. 验证自定义Filter是否被调用
你可以在PasswordLoginFilter里加个日志或者断点,确认它是否正常触发:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; public class PasswordLoginFilter extends UsernamePasswordAuthenticationFilter { private static final Logger logger = LoggerFactory.getLogger(PasswordLoginFilter.class); @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { logger.info("自定义登录Filter被调用啦!"); return super.attemptAuthentication(request, response); } }
最后,给你一个完整的修正后配置参考
<beans:import resource="../security-formAuth.xml" /> <http use-expressions="true"> <intercept-url pattern="/login.jsp" access="permitAll()" /> <intercept-url pattern="/login" access="permitAll()" /> <intercept-url pattern="/**" access="isAuthenticated()" /> <custom-filter ref="formAuthenticationFilter" before="FORM_LOGIN_FILTER"/> </http> <beans:bean class="game.security.filter.PasswordLoginFilter" id="formAuthenticationFilter"> <beans:property ref="authenticationManager" name="authenticationManager" /> <beans:property name="filterProcessesUrl" value="/login" /> <beans:property name="authenticationSuccessHandler"> <beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler"> <beans:property name="defaultTargetUrl" value="/Website/categoryLevels.html" /> </beans:bean> </beans:property> <beans:property name="authenticationFailureHandler"> <beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> <beans:property name="defaultFailureUrl" value="/login.jsp" /> </beans:bean> </beans:property> </beans:bean> <authentication-manager id="authenticationManager"> <authentication-provider> <user-service> <user name="user1" password="test" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
额外小建议
为了避免路径硬编码的问题,建议在JSP表单里用JSTL的<c:url>标签生成action路径:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <form name="f" method="post" action="<c:url value='/login'/>">
这样会自动处理应用的上下文路径,防止部署路径变化导致的错误。
内容的提问来源于stack exchange,提问作者Lea
相关产品推荐
相关产品推荐

