Spring Authorization Server自定义登录页failureForwardUrl失效问题
问题背景
我正在使用新版Spring Authorization Server,项目引入的相关依赖如下:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <version>0.2.3</version> </dependency>
需要为授权服务器配置自定义登录页面,已完成两个配置类的Bean编写:
AuthorizationServerConfig.java配置:
@Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); return http.cors(Customizer.withDefaults()) .formLogin() .and().build(); }
SecurityConfig.java配置:
@Bean SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .cors(withDefaults()) .authorizeRequests(authorizeRequests -> authorizeRequests.mvcMatchers("/custom-login", "/css/**", "/js**", "/image/**").permitAll().anyRequest().authenticated() ) .formLogin() .loginPage("/custom-login").failureForwardUrl("/custom-login?error"); return http.build(); }
运行时异常表现:
用户输入错误的登录凭证时,系统不会跳转至
/custom-login?error路径,而是直接跳转至不带参数的/custom-login路径,配置的.failureForwardUrl("/custom-login?error");未生效。
对照默认场景(不配置自定义登录页),输入错误凭证时会正常跳转至/login?error=some-error路径并携带错误参数。
根因分析
- 配置方法选型错误:
failureForwardUrl()实现的是服务端内部请求转发,不会触发客户端重定向,浏览器地址栏不会变更,且Spring Security默认的转发失败处理器不会解析配置路径上的query参数,无法实现带参数跳转效果。要实现地址栏跳转到带error参数的登录页,需要使用基于302重定向的failureUrl()方法。 - 过滤器链配置冲突:授权服务器的SecurityFilterChain被设置了最高优先级,且在该链中单独开启了未做任何自定义配置的
formLogin()逻辑。所有授权流程相关的请求会先被这个高优先级链拦截,其中默认的表单登录失败逻辑会覆盖低优先级defaultSecurityFilterChain中写的自定义配置,导致配置不生效。 - 路径匹配笔误:静态资源放行规则中
/js**缺少路径分隔符,正确匹配规则应为/js/**,该问题会导致静态资源加载异常,间接影响登录页逻辑。
修复方案
1. 调整授权服务器过滤器链配置
移除授权服务器链中多余的formLogin配置,仅在该链中配置认证入口跳转到自定义登录页,所有表单登录逻辑统一交给后续的defaultSecurityFilterChain处理:
@Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http .cors(Customizer.withDefaults()) // 配置未认证请求统一跳转到自定义登录页 .exceptionHandling(exceptions -> exceptions .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/custom-login")) ); return http.build(); }
2. 修正默认安全链配置
替换失败跳转方法、修正静态资源匹配规则、补全登录配置:
@Bean SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .cors(withDefaults()) .authorizeRequests(authorizeRequests -> authorizeRequests // 修正js资源路径匹配规则 .mvcMatchers("/custom-login", "/css/**", "/js/**", "/image/**").permitAll() .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/custom-login") // 改用failureUrl实现302重定向跳转,携带error参数 .failureUrl("/custom-login?error") // 配置登录表单提交的处理接口,与前端表单action地址保持一致 .loginProcessingUrl("/login") .permitAll() ); return http.build(); }
3. 验证逻辑
配置修改重启后,输入错误登录凭证时,浏览器会收到302响应,自动跳转到/custom-login?error地址,地址栏可见error参数,前端页面可通过request对象读取该参数展示错误提示。
额外注意:不要通过URL传递具体的错误详情,避免敏感信息泄露。如果需要自定义错误提示内容,可自定义
AuthenticationFailureHandler实现,将错误信息存入Session后再跳转,在登录页读取展示即可。
内容的提问来源于stack exchange,提问作者Navigator
相关产品推荐
相关产品推荐

