Spring Security自定义登录页登录验证及相关异常问题咨询
1. 登录请求地址与返回规则说明
当仅配置formLogin().loginPage("/login")时,Spring Security默认将/login同时作为登录页GET访问地址和登录提交POST接收地址,会自动生成对应的POST接口处理登录逻辑。
默认返回规则适配服务端渲染场景:
- 登录成功:返回302状态码,重定向到
defaultSuccessUrl配置的地址,未配置默认重定向到根路径/ - 登录失败:返回302状态码,重定向到
failureUrl配置的地址,未配置默认重定向到/login?error
你当前无论输入什么账号都返回200的原因:axios默认发送JSON格式请求,Spring Security默认的登录过滤器仅支持application/x-www-form-urlencoded格式的参数,请求未进入登录校验逻辑,直接返回了自定义登录页的GET响应内容,因此状态码始终为200。
2. loadUserByUsername方法未被调用原因
该方法未触发的核心原因是登录请求没有被Spring Security的登录校验过滤器拦截处理,常见场景如下:
- 登录请求参数格式不符合要求,不是表单格式,过滤器直接跳过校验
- 安全配置中把
/login的POST请求加入了白名单,跳过了安全校验链 - 自定义的
UserDetailsService实现类未添加@Service/@Component注解,未被Spring容器托管,注入到配置类的实例为空
3. 自定义loginProcessingUrl的要求
配置loginProcessingUrl("/api/login")仅修改了Spring Security登录过滤器拦截的POST请求地址,默认不需要自行实现该端点的逻辑,过滤器会自动处理。如果需要完全自定义登录逻辑,该端点需要满足以下要求:
- 必须支持POST请求
- 若使用默认的参数解析逻辑,参数名需要对应
username和password,可通过usernameParameter、passwordParameter配置修改参数名 - 若要接收JSON格式参数,需要自定义
UsernamePasswordAuthenticationFilter,重写attemptAuthentication方法解析JSON参数 - 需要在安全配置中放开该端点的POST访问权限,不需要登录即可访问
补充1:前后端分离场景的返回码规则
Spring Security默认的重定向逻辑不适合前后端分离场景,需要自定义authenticationSuccessHandler和authenticationFailureHandler适配异步请求的返回规则,可按业务需求自定义状态码:
- 登录成功:返回200状态码,携带自定义成功信息
- 用户名不存在或密码错误:返回401状态码,携带对应错误提示
- 其他异常场景按业务规则返回对应状态码
你当前的axios请求发送的是JSON格式参数,默认过滤器不支持,因此无法拿到正确的校验结果,需要先自定义过滤器解析JSON参数。
补充2:权限不足跳转405错误原因
出现405错误是因为accessDeniedPage默认使用转发逻辑,会将当前请求的方法(POST)一并带到转发地址,而你的/login接口仅支持GET请求,因此触发请求方法不支持的错误。
要实现直接GET重定向的预期效果,需要将accessDeniedPage替换为自定义的accessDeniedHandler,在处理器中直接返回302重定向到/login?denied即可,登录失败跳转同理也可使用failureHandler代替failureUrl避免转发问题。
内容的提问来源于stack exchange,提问作者Peter Kronenberg

