自定义Spring Authorization Server登录页

一、鸣谢

首先要声明一些感谢:

  1. 感谢官方文档的缺失、反复造成我下面这条感谢
  2. 感谢那些胡说八道、顾彼失此的某DN文章,让我在冲向坑里的道路上一往无前

废话不多说,看剑!

本文来自:博客园-去哪里吃鱼-自定义Spring Authorization Server登录页

二、版本信息

本文基于如下以来版本信息,官方代码如有变动,请自行阅读源码解决问题。

友情提示:不要照抄某DN、AI内容,避免浪费生命。

xml 复制代码
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
	<version>3.3.10</version>
</dependency>

<!-- 上面的依赖引用的 spring-security-oauth2-authorization-server 版本,这里只做提示,不用引入 -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>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 样式文件,鉴于一些众所周知的原因,这个样式文件访问不了,所以登录页加载会很慢。

此外,每个产品也会相应的设计具有自己产品风格特性的登录页,这让自定义登录页成为了一个硬性需求。

如下为 只修改登录页 的处理过程,一些项目配置如下

四、修改 SpringSecurity 配置

贴一段基于官方demo的修改后的配置代码:

java 复制代码
@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();
}

现在来说一下注意事项:

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

五、修改 Spring Authorization Server 配置

同样基于官方demo的修改后的配置:

java 复制代码
@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")

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

六、其他

自定义授权确认页面不在此篇幅范围之内,这个版本当客户端请求的 role 是一个值的时候不会出现授权确认页面。

我解决这种自定义问题的思路:

研究 Spring Security 的配置方式,如:SecurityBuilder,SecurityConfiger,从而找到自己出现问题所在的步骤,针对性的去调整

看到这里,希望对你有所帮助。

相关推荐
佛祖让我来巡山20 天前
小明网站双登录系统实现——微信授权登录+用户名密码登录完整指南
oauth2·springsecurity·微信授权登录
佛祖让我来巡山21 天前
Spring Security 鉴权流程与过滤器链深度剖析
springsecurity·authenticationmanager
佛祖让我来巡山21 天前
大型项目基于Spring Security的登录鉴权与数据权限控制完整方案
springsecurity·保姆级鉴权·大型项目登录认证
佛祖让我来巡山21 天前
Spring Security前后端分离接入流程保姆级教程
权限校验·springsecurity·登录认证
佛祖让我来巡山22 天前
Spring Security 认证流程闭环与调用链路详解
springsecurity·authenticationmanager
佛祖让我来巡山22 天前
小明的Spring Security入门到深入实战
springsecurity
佛祖让我来巡山23 天前
⚠️登录认证功能的成长过程:整体概述
安全·登录·springsecurity·登录认证·认证授权
码熔burning3 个月前
Spring Security 深度学习(六): RESTful API 安全与 JWT
安全·spring·restful·springsecurity
A尘埃3 个月前
SpringSecurity版本的不同配置
认证·springsecurity·安全配置·不同版本
世纪摆渡人5 个月前
SpringSecurity-SpringSecurity入门介绍
springsecurity