如何全面升级spring-boot-2.x及Spring-security-oauth2

本文主要讲述了在将老项目从spring-boot-1.5.x和spring-security-oauth2-2.x升级到新版本后遇到的登录回跳问题。在升级过程中,由于Spring Framework和Spring Security的版本变化,导致UsernamePasswordAuthenticationFilter未正常拦截登录请求。作者通过源码分析,找出问题所在并提出解决方案,即修改NotOAuthRequestMatcher的匹配规则,避免自定义请求被错误处理。

背景介绍

老的项目基于spring-boot-1.5.x、spring-security-oauth2-2.x实现的sso,在近期的安全漏洞扫描中发现如下2个漏洞:

漏洞

涉及jar

修复方案

Spring Framework JDK >= 9 远程代码执行漏洞(CVE-2022-22965)

spring-core-4.3.12.RELEASE.jar

升级官方安全版本 >= 5.3.18/5.2.20

Spring Security RegexRequestMatcher 认证绕过漏洞(CVE-2022-22978)

spring-security-core-4.2.3.RELEASE.jar

5.5.x 版本使用者建议升级至5.5.7及其以上;
5.6.x 版本使用者建议升级至5.6.4及其以上

然后笔者的同事将spring-boot升级到了2.5.14;将spring-security-oauth2升级到了2.1.0、RELEASE,这样一来,spring-core的版本被间接的升级到了5.3.20,spring-security-core版本变成了5.5.8(主要是spring-boot决定的)。

因为spring-boot-1.x和2.x之间的差距,同步的对项目依赖和代码做了微调。这里不再列出。不是今天的重点。

项目终于能成功启动了,但是一个致命的问题出来了,登录成功后,不能正确的回跳到redirect_uri指定的地址。这里如果你对spring-security-oauth2实现登录认证不熟悉的,可以参考使用Spring Security搭建一套OAuth 2.0架构

先说一下升级前是正

<think>我们在Spring Boot 3.3.5环境下讨论Spring Security OAuth2的使用和配置。根据引用[2]和[4],需要注意: 1. 传统的Spring Security OAuth2项目已经弃用,官方推荐使用Spring Authorization Server(内置在Spring Security 5.7+)。 2. 对于Spring Boot 3.x(包括3.3.5),应该使用spring-security-oauth2-authorization-server。 因此,在Spring Boot 3.3.5中,我们不会使用旧的spring-security-oauth2客户端库,而是使用新的Spring Authorization Server(用于构建授权服务器)和Spring Security OAuth2客户端(用于构建客户端应用)。 用户问题中提到了“接入GitHub社区登录”,这是一个典型的OAuth2客户端场景(即我们的应用作为客户端,使用GitHub作为授权服务器)。因此,我们重点讨论如何在Spring Boot 3.3.5中配置OAuth2客户端(使用GitHub登录)。 步骤: 1. 添加依赖 2. 配置GitHub OAuth2客户端信息 3. 配置安全规则 4. 创建用户服务(可选,用于将GitHub登录用户关联到本地用户) 注意:这里我们只讨论客户端配置(即使用GitHub登录),不讨论授权服务器(即我们自己提供OAuth2服务)。 具体步骤: 1. 添加依赖(Maven): ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> ``` 2. 在`application.yml`(或`application.properties`)中配置GitHub客户端信息: ```yaml spring: security: oauth2: client: registration: github: # 注册ID,可以自定义,但通常用github client-id: your-github-client-id client-secret: your-github-client-secret scope: user:email # 根据需要申请scope,例如获取用户邮箱 ``` 注意:需要先在GitHub上注册OAuth应用(在GitHub的Settings -> Developer settings -> OAuth Apps中创建),获取client-id和client-secret。 3. 配置安全规则(Java配置): ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize .requestMatchers("/", "/login**", "/error**").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .loginPage("/login") // 自定义登录页面(可选) ); return http.build(); } } ``` 4. 如果需要自定义用户信息映射(例如,将GitHub返回的用户信息映射到我们自己的用户对象),可以配置一个自定义的`OAuth2UserService`: ```java import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; @Service public class CustomOAuth2UserService extends DefaultOAuth2UserService { @Override public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2UserAuthenticationException { OAuth2User user = super.loadUser(userRequest); // 在这里进行自定义处理,例如提取用户信息并转换为本地用户 return user; } } ``` 然后在安全配置中指定这个自定义服务: ```java @Configuration @EnableWebSecurity public class SecurityConfig { private final CustomOAuth2UserService customOAuth2UserService; public SecurityConfig(CustomOAuth2UserService customOAuth2UserService) { this.customOAuth2UserService = customOAuth2UserService; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize // ... 同上 ... ) .oauth2Login(oauth2 -> oauth2 .userInfoEndpoint(userInfo -> userInfo .userService(customOAuth2UserService) ) ); return http.build(); } } ``` 常见问题及解决方案: 1. 问题:登录后无法获取用户邮箱? 原因:GitHub默认返回的用户信息中不包含邮箱,需要申请`user:email` scope,并且在获取用户信息时显式请求邮箱字段。 解决方案:在配置中确保scope包含`user:email`,并在自定义的`OAuth2UserService`中通过GitHub的API获取邮箱(因为邮箱信息在另一个端点)。 在`CustomOAuth2UserService`中,可以这样获取邮箱: ```java // 在loadUser方法内 String email = getEmailFromGitHub(userRequest.getAccessToken()); // 然后将邮箱信息添加到用户属性中 ``` 其中`getEmailFromGitHub`方法需要调用GitHub的API(https://api.github.com/user/emails)并解析返回的邮箱列表(可能需要选择主邮箱)。 2. 问题:在Spring Boot 3.x中配置OAuth2客户端时遇到属性无法解析? 检查依赖是否正确引入了`spring-boot-starter-oauth2-client`,并且配置的property路径是否正确(注意:在Spring Boot 3.x中,配置路径为`spring.security.oauth2.client.registration`)。 3. 问题:登录后重定向到/login?或者无限重定向? 检查安全配置中的`authorizeHttpRequests`,确保登录页面(如`/login`)和重定向的端点(如`/login/oauth2/code/*`)是允许访问的(上面示例中通过`/login**`已经允许了所有以/login开头的路径)。同时,确保错误页面(如`/error`)也允许访问。 4. 问题:使用Spring Boot 3.x时出现类或方法找不到? 确保没有引入旧的spring-security-oauth2-client依赖(如`org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure`),因为旧库不兼容Spring Boot 3.x。 总结:在Spring Boot 3.3.5中使用Spring Security实现GitHub登录,主要步骤是添加OAuth2客户端依赖、配置客户端注册信息、配置安全规则。如果需要更复杂的用户信息处理,可以通过自定义`OAuth2UserService`实现。 参考文献: [^1]: GitHub的OAuth2登录流程 [^2]: Spring Security OAuth2已弃用,推荐迁移到Spring Authorization Server [^4]: spring-security-oauth2-authorization-server与Spring Boot 3.x整合 §§相关问题§§ 1. 除了GitHub,如何在Spring Boot 3.3.5中配置Google登录? 2. 如何自定义OAuth2登录成功后的处理逻辑(比如重定向到特定页面)? 3.Spring Boot 3.3.5中如何同时配置多个OAuth2提供商(如GitHub和Google)? </think>在 Spring Boot 3.3.5 环境下使用 Spring Security OAuth2 进行 GitHub 社区登录的配置和使用方法如下(基于官方推荐的最新方案): ### 一、核心依赖配置 根据引用[2]和[4],**传统 Spring Security OAuth2 已弃用**,需使用新的授权服务器组件: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> <!-- 客户端支持 --> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <version>1.1.2</version> <!-- 适配 Spring Boot 3.3.5 --> </dependency> ``` ### 二、GitHub OAuth2 登录配置 1. **GitHub 应用注册**: - 在 GitHub → Settings → Developer settings → OAuth Apps 创建应用 - 获取 `Client ID` 和 `Client Secret` - 设置回调地址:`http://localhost:8080/login/oauth2/code/github` 2. **application.yml 配置**: ```yaml spring: security: oauth2: client: registration: github: client-id: your_github_client_id client-secret: your_github_client_secret scope: user:email, read:user # 所需权限 provider: github: authorization-uri: https://github.com/login/oauth/authorize token-uri: https://github.com/login/oauth/access_token user-info-uri: https://api.github.com/user ``` ### 三、安全配置类 ```java @Configuration @EnableWebSecurity public class SecurityConfig { @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/login**").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .loginPage("/login") // 自定义登录页 .defaultSuccessUrl("/home", true) // 登录成功跳转 ) .logout(logout -> logout .logoutSuccessUrl("/") ); return http.build(); } } ``` ### 四、用户信息处理(可选) 自定义用户映射服务: ```java @Service public class CustomOAuth2UserService extends DefaultOAuth2UserService { @Override public OAuth2User loadUser(OAuth2UserRequest request) { OAuth2User user = super.loadUser(request); Map<String, Object> attributes = user.getAttributes(); // 提取GitHub返回的用户信息(示例) String username = (String) attributes.get("login"); String email = (String) attributes.get("email"); // 构建本地用户实体 return new CustomUser(username, email, user.getAuthorities()); } } ``` ### 五、常见问题解决方案 1. **401 认证失败**: - 检查 GitHub 应用回调地址是否与配置一致 - 确认 `client-id` 和 `client-secret` 无拼写错误 - 确保 GitHub 应用的 `Authorization callback URL` 包含 `/login/oauth2/code/github` 2. **Scope 权限不足**: ```yaml # 增加所需权限 scope: - user:email - read:org ``` 3. **配置不生效**: - 确认使用 `@Configuration` 注解配置类 - 检查是否存在多个 `WebSecurityConfigurerAdapter` 冲突 4. **旧版兼容问题**: - 移除传统依赖 `spring-security-oauth2-autoconfigure` - 避免使用已弃用的 `@EnableOAuth2Client` 注解 ### 六、流程说明(OAuth2 授权码流程) 1. 用户访问 `/login` 重定向到 GitHub 授权页 2. GitHub 回调到 `/login/oauth2/code/github` 3. Spring Security 自动交换令牌并获取用户信息 4. 通过 `CustomOAuth2UserService` 映射为本地用户[^4] > **重要提示**:Spring Boot 3.x 必须使用 JDK 17+,授权服务器配置需严格遵循 [Spring Authorization Server 文档](https://docs.spring.io/spring-authorization-server/docs/current/reference/html/getting-started.html)[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值