蔺堰 发表于 2025-6-3 10:26:24

自定义Spring Authorization Server登录页

一、鸣谢

首先要声明一些感谢:

[*]感谢官方文档的缺失、反复造成我下面这条感谢
[*]感谢那些胡说八道、顾彼失此的某DN文章,让我在冲向坑里的道路上一往无前
废话不多说,看剑!
本文来自:博客园-去哪里吃鱼-自定义Spring Authorization Server登录页
二、版本信息

本文基于如下以来版本信息,官方代码如有变动,请自行阅读源码解决问题。
友情提示:不要照抄某DN、AI内容,避免浪费生命。
<dependency>
        <groupId>org.springframework.boot</groupId>
        spring-boot-starter-oauth2-authorization-server</artifactId>
        <version>3.3.10</version>
</dependency>


<dependency>
        <groupId>org.springframework.security</groupId>
        spring-security-oauth2-authorization-server</artifactId>
        <version>1.3.5</version>
</dependency>三、过滤器链介绍

使用 Spring Authorization Server 开发授权服务器,必然不可少要配置两个 SecurityFilterChain过滤器链:

[*]SpringSecurity的过滤器链
[*]授权服务的过滤器链
这两条过滤器链不会冲突,但是要确保授权服务器的过滤器链在SpringSecurity链之前加载,在代码当中可以使用@Order(0)注解来调整,注解中的整数参数越小,加载顺序就越靠前
调整的目的是:
SpringSecurity的过滤器链默认所有请求都需要认证,把授权服务的过滤器链提前,可以避免如下默认授权相关请求不受SpringSecurity的过滤器链影响

[*]/oauth2/authorize
[*]/oauth2/token
[*]/oauth2/jwks
[*]/userinfo
[*]/login
[*]...
如下基于 授权码 模式进行开发,默认的,以 GET 方式请求的 /login 是跳转到登录页,以 POST 方式请求的 /login 则是处理登录请求,Spring 官方以硬编码的形式提供了一个默认登录页,其中引用了bootstrap 样式文件,鉴于一些众所周知的原因,这个样式文件访问不了,所以登录页加载会很慢。
此外,每个产品也会相应的设计具有自己产品风格特性的登录页,这让自定义登录页成为了一个硬性需求。
如下为 只修改登录页 的处理过程,一些项目配置如下

[*]应用 context-path 自定义为 'auth'
[*]自定义登录页请求地址为: http://domain/auth/i/login
四、修改 SpringSecurity 配置

贴一段基于官方demo的修改后的配置代码:
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
        throws Exception {
        http
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers("/i/**","/login**").permitAll()
                        .anyRequest().authenticated()
                )
                .cors(AbstractHttpConfigurer::disable)
                .csrf(AbstractHttpConfigurer::disable)
                .formLogin(form -> form.loginPage("/i/login").loginProcessingUrl("/login"));
        return http.build();
}现在来说一下注意事项:

[*]登录页请求由SpringSecurity的过滤器链处理,因为授权服务过滤器链没有设置 formLogin,它只处理相关接口
[*]在配置 formLogin 的时候,loginPage 和 loginProcessingUrl 都需要配置,如果不配置 loginProcessingUrl,它则会用 loginPage 的 url来处理登录请求
[*]除了登录页请求放开,登录请求也要放开,交由授权服务过滤器链处理,在代码中就是 requestMatchers("/i/**","/login**").permitAll()
五、修改 Spring Authorization Server 配置

同样基于官方demo的修改后的配置:
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        http.getConfigurer(OAuth2AuthorizationServerConfigurer.class).oidc(withDefaults());
        http.exceptionHandling((exceptions) -> exceptions
                .defaultAuthenticationEntryPointFor(
                        new LoginUrlAuthenticationEntryPoint(domain + "/auth/i/login"),
                        new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
                )
        )
        .oauth2ResourceServer((resourceServer) -> resourceServer.jwt(Customizer.withDefaults()));
        return http.build();
}注意事项之在代码 new LoginUrlAuthenticationEntryPoint(domain + "/auth/i/login") 中

[*]domain 变量仅在有需要的情况下使用,也可以不用
[*]构造函数中的地址,一定一定要与上一章节中的 loginPage 地址相同,不要被 xxxEntryPoint 迷惑,这里就是指登录页地址!
六、其他

自定义授权确认页面不在此篇幅范围之内,这个版本当客户端请求的 role 是一个值的时候不会出现授权确认页面。
我解决这种自定义问题的思路:
研究 Spring Security 的配置方式,如:SecurityBuilder,SecurityConfiger,从而找到自己出现问题所在的步骤,针对性的去调整
看到这里,希望对你有所帮助。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

甦忻愉 发表于 2025-10-19 00:41:32

东西不错很实用谢谢分享

材部 发表于 2025-11-18 22:09:00

谢谢分享,试用一下

户烫擞 发表于 2025-12-5 16:13:29

收藏一下   不知道什么时候能用到

劳怡月 发表于 2025-12-6 19:15:11

谢谢分享,辛苦了

乳杂丫 发表于 4 天前

感谢分享,下载保存了,貌似很强大
页: [1]
查看完整版本: 自定义Spring Authorization Server登录页