(十五)快速集成 GitHub 与 Gitee 的社交登录
1. 前言
在微服务与前后端分离架构中,第三方社交登录已成为提升用户体验的重要功能。社交登录可以有效降低用户注册成本,同时利用第三方平台的账号体系,实现快速认证与信息获取。Spring Security 6 作为 Java 生态中的安全框架,通过 OAuth2 协议简化了第三方认证的集成流程。
本章节笔者将通过完整代码案例,讲解如何基于 Spring Security 6 实现 GitHub 和 Gitee 的社交登录功能。
2. 原理分析
回顾上一章节介绍的 OAuth 2.0 授权码流程(最新 Spring Security 实战教程(十四)OAuth2.0 精讲 - 四种授权模式与资源服务器搭建):

其主要流程包括:
- 跳转授权:客户端(我们的网站)将用户重定向至第三方授权服务器的授权端点,携带
client_id、redirect_uri、scope 等参数。
- 用户登录并同意:用户在第三方平台完成登录后,同意授权给客户端指定权限。
- 回调获取授权码:授权服务器重定向回客户端注册的
redirect_uri,并在查询参数中附带 code。
- 交换令牌:客户端后端使用
code、client_secret 等向授权服务器的令牌端点发起 POST 请求,获取 access_token。
- 获取用户信息:客户端携带
access_token 调用用户信息端点,解析并登录或注册用户。
3. 开发准备
3.1 初始化项目
继续基于之前的项目构建子项目 social-login-spring-security,pom 文件引入项目依赖:
1 2 3 4 5 6
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> </dependencies>
|
GitHub/Gitee 开发者账号:用于注册 OAuth 应用。
3.2 注册 GitHub OAuth 应用
访问 GitHub 设置 → Developer settings → OAuth Apps → New OAuth App,填写应用名、主页 URL、授权回调 URL。

填写应用信息:默认的重定向 URI 模板为 {baseUrl}/login/oauth2/code/{registrationId}。registrationId 是 ClientRegistration 的唯一标识符。
例如 GitHub 固定写法则为:{baseUrl}/login/oauth2/code/github。

获取应用程序 ID,生成应用程序密钥:保存好生成的 Client ID 与 Client Secret。

3.3 注册 Gitee OAuth 应用
登录 Gitee,访问 Gitee 应用管理,创建新应用。

提交创建应用后会得到 Client ID 和 Client Secret。
4. 实战案例
完成上述准备工作后,我们开始对项目进行配置。
4.1 配置 application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| spring: application: name: social-login-spring-security security: oauth2: client: registration: github: client-id: YOUR_CLIENT_ID client-secret: YOUR_CLIENT_SECRET scope: user:email redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" authorization-grant-type: authorization_code client-name: github gitee: client-id: YOUR_CLIENT_ID client-secret: YOUR_CLIENT_SECRET scope: user_info client-name: Gitee authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" provider: gitee provider: gitee: authorization-uri: https://gitee.com/oauth/authorize token-uri: https://gitee.com/oauth/token user-info-uri: https://gitee.com/api/v5/user user-name-attribute: name server: port: 8089
|
4.2 自定义用户信息处理
GitHub 和 Gitee 返回的用户数据结构不同,需统一处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Override public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { DefaultOAuth2UserService delegate = new DefaultOAuth2UserService(); OAuth2User oAuth2User = delegate.loadUser(userRequest);
String registrationId = userRequest.getClientRegistration().getRegistrationId(); Map<String, Object> attributes = oAuth2User.getAttributes();
if ("github".equals(registrationId)) { return new DefaultOAuth2User( oAuth2User.getAuthorities(), attributes, "login" ); } else if ("gitee".equals(registrationId)) { return new DefaultOAuth2User( oAuth2User.getAuthorities(), attributes, "name" ); } throw new OAuth2AuthenticationException("Unsupported platform"); } }
|
4.3 SecurityConfig 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Configuration @EnableWebSecurity public class SecurityConfig {
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize .requestMatchers("/", "/public/**").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .userInfoEndpoint(userInfo -> userInfo .userService(customOAuth2UserService()) ) ) .csrf(AbstractHttpConfigurer::disable); return http.build(); }
@Bean public OAuth2UserService<OAuth2UserRequest, OAuth2User> customOAuth2UserService() { return new CustomOAuth2UserService(); } }
|
4.4 控制器与页面
编写自定义的登录页,授权登录后返回授权的用户信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Controller public class IndexController { @GetMapping("/") public String index(Model model, @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient, @AuthenticationPrincipal OAuth2User oauth2User) { model.addAttribute("userName", oauth2User.getName()); model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName()); model.addAttribute("userAttributes", oauth2User.getAttributes()); return "index"; }
@GetMapping("/user") @ResponseBody public Map<String, Object> userInfo(OAuth2AuthenticationToken authentication) { OAuth2User user = authentication.getPrincipal(); return Map.of( "username", user.getName(), "authorities", user.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.toList()) ); } }
|
Thymeleaf 模板页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"> <head> <title>Spring Security - OAuth 2.0 Login</title> <meta charset="utf-8" /> </head> <body> <div style="float: right" th:fragment="logout" sec:authorize="isAuthenticated()"> <div style="float:left"> <span style="font-weight:bold">User: </span><span sec:authentication="name"></span> </div> <div style="float:none"> </div> <div style="float:right"> <form action="#" th:action="@{/logout}" method="post"> <input type="submit" value="Logout" /> </form> </div> </div> <h1>OAuth 2.0 Login with Spring Security</h1> <div> You are successfully logged in <span style="font-weight:bold" th:text="${userName}"></span> via the OAuth 2.0 Client <span style="font-weight:bold" th:text="${clientName}"></span> </div> <div> </div> <div> <span style="font-weight:bold">User Attributes:</span> <ul> <li th:each="userAttribute : ${userAttributes}"> <span style="font-weight:bold" th:text="${userAttribute.key}"></span>: <span th:text="${userAttribute.value}"></span> </li> </ul> </div> </body> </html>
|
5. 测试验证
- 访问首页:
http://localhost:8089,跳转至 Spring Security 默认登录页。
注:应用回调地址如果填写的是 localhost,本地访问项目也需保持 localhost 访问;若使用 127.0.0.1 会导致回调地址不一致,出现回调地址错误的异常。
- 选择登录方式:点击
GitHub 或 Gitee 按钮,跳转至对应授权页面。
GitHub 授权页

Gitee 授权页

- 授权登录:同意授权后,自动跳转回应用,显示用户信息。
- 访问
http://localhost:8089/user 显示经过处理的用户信息。
1 2 3 4 5 6 7
| { "authorities": [ "OAUTH2_USER", "SCOPE_user:email" ], "username": "授权返回的用户名" }
|
6. 常见问题与扩展
- 回调地址不匹配:确保
redirect-uri 与注册应用时填写的一致。
- 跨域问题:前端分离项目需配置
CorsFilter。
- 用户信息字段缺失:检查
user-info-uri 和 user-name-attribute 配置。
7. 总结
通过 Spring Security 6 的 OAuth2 Client 模块,开发者可以快速集成主流社交登录功能。本章节案例以 GitHub 和 Gitee 为例,展示了从应用注册到用户信息处理的完整流程,适用于需要第三方登录的 Web 应用场景。
后续章节笔者将继续扩展支持微信、支付宝、QQ、微博等更多平台,进一步提升用户体验。