最新Spring Security实战教程(十五)快速集成 GitHub 与 Gitee 的社交登录

🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志

🎐 个人CSND主页------Micro麦可乐的博客

🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战

🌺《RabbitMQ》专栏19年编写主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战

🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解

🌛《开源项目》本专栏主要介绍目前热门的开源项目,带大家快速了解并轻松上手使用

✨《开发技巧》本专栏包含了各种系统的设计原理以及注意事项,并分享一些日常开发的功能小技巧

💕《Jenkins实战》专栏主要介绍Jenkins+Docker的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程

🌞《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧,代码样例完整

🌞《Spring Security》专栏中我们将逐步深入Spring Security的各个技术细节,带你从入门到精通,全面掌握这一安全技术
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

最新Spring Security实战教程(十五)快速集成 GitHub 与 Gitee 的社交登录

  • [1. 前言](#1. 前言)
  • [2. 原理分析](#2. 原理分析)
  • [3. 开发准备](#3. 开发准备)
    • [3.1 初始化项目](#3.1 初始化项目)
    • [3.2 注册 GitHub OAuth 应用](#3.2 注册 GitHub OAuth 应用)
    • [3.3 注册 Gitee OAuth 应用](#3.3 注册 Gitee OAuth 应用)
  • [4. 实战案例](#4. 实战案例)
    • [4.1 配置 application.yml](#4.1 配置 application.yml)
    • [4.2 自定义用户信息处理](#4.2 自定义用户信息处理)
    • [4.3 SecurityConfig配置](#4.3 SecurityConfig配置)
    • [4.4 控制器与页面](#4.4 控制器与页面)
  • [5. 测试验证](#5. 测试验证)
  • [6. 常见问题与扩展](#6. 常见问题与扩展)
  • [7. 总结](#7. 总结)

回顾链接:
最新Spring Security实战教程(一)初识Spring Security安全框架
最新Spring Security实战教程(二)表单登录定制到处理逻辑的深度改造
最新Spring Security实战教程(三)Spring Security 的底层原理解析
最新Spring Security实战教程(四)基于内存的用户认证
最新Spring Security实战教程(五)基于数据库的动态用户认证传统RBAC角色模型实战开发
最新Spring Security实战教程(六)最新Spring Security实战教程(六)基于数据库的ABAC属性权限模型实战开发
最新Spring Security实战教程(七)方法级安全控制@PreAuthorize注解的灵活运用
最新Spring Security实战教程(八)Remember-Me实现原理 - 持久化令牌与安全存储方案
最新Spring Security实战教程(九)前后端分离认证实战 - JWT+SpringSecurity无缝整合
最新Spring Security实战教程(十)权限表达式进阶 - 在SpEL在安全控制中的高阶魔法
最新Spring Security实战教程(十一)CSRF攻防实战 - 从原理到防护的最佳实践
最新Spring Security实战教程(十二)CORS安全配置 - 跨域请求的安全边界设定
最新Spring Security实战教程(十三)会话管理机制 - 并发控制与会话固定攻击防护
最新Spring Security实战教程(十四)OAuth2.0精讲 - 四种授权模式与资源服务器搭建

专栏更新完毕后,博主将会上传所有章节代码到CSDN资源免费给大家下载,如你不想等后续章节代码需提前获取,可以私信或留言!

1. 前言

在微服务与前后端分离架构中,第三方社交登录已成为提升用户体验的重要功能。社交登录可以有效降低用户注册成本,同时利用第三方平台的账号体系,实现快速认证与信息获取。Spring Security 6 作为 Java 生态中的安全框架,通过 OAuth2 协议简化了第三方认证的集成流程。

本章节博主将通过完整代码案例,讲解如何基于 Spring Security 6 实现 GitHubGitee 的社交登录功能。


2. 原理分析

回顾一下我们上一个章节,OAuth 2.0 授权码流程 【最新Spring Security实战教程(十四)OAuth2.0精讲 - 四种授权模式与资源服务器搭建】

其主要包括:

  • 跳转授权 :客户端(我们的网站)将用户重定向至第三方授权服务器的授权端点,携带 client_idredirect_uriscope 等参数
  • 用户登录并同意:用户在第三方平台完成登录后,同意授权给客户端指定权限
  • 回调获取授权码 :授权服务器重定向回客户端注册的 redirect_uri,并在查询参数中附带 code
  • 交换令牌 :客户端后端使用 codeclient_secret 等向授权服务器的令牌端点发起 POST 请求,获取 access_token
  • 获取用户信息 :客户端携带 access_token 调用用户信息端点,解析并登录或注册用户

3. 开发准备

3.1 初始化项目

还是继续基于我们之前的项目构建子项目 social-login-spring-security, pom文件引入项目依赖

xml 复制代码
<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 settingsOAuth AppsNew 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 IDClient Secret


4. 实战案例

完成了上述的准备,我们开始来对我们的项目进行配置

4.1 配置 application.yml

yaml 复制代码
#最新Spring Security实战教程(十五)快速集成 GitHub 与 Gitee 的社交登录
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 自定义用户信息处理

GitHubGitee 返回的用户数据结构不同,需统一处理:

java 复制代码
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"  // GitHub 的用户名字段
            );
        } else if ("gitee".equals(registrationId)) {
            return new DefaultOAuth2User(
                oAuth2User.getAuthorities(),
                attributes,
                "name"  // Gitee 的用户名字段
            );
        }
        throw new OAuth2AuthenticationException("Unsupported platform");
    }
}

4.3 SecurityConfig配置

java 复制代码
@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 控制器与页面

编写自定义的登陆页,授权登陆返回授权的用户信息

java 复制代码
@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());
        //TODO 可以增加与项目用户注册、绑定等业务service
        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模版页面

html 复制代码
<!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">&nbsp;</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>&nbsp;</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 会导致回调地址不一致出现回调地址错误的异常

  • 选择登录方式:点击 GitHubGitee 按钮,跳转至对应授权页面

GitHub授权页

Gitee授权页

  • 授权登录:同意授权后,自动跳转回应用,显示用户信息
  • 访问 http://localhost:8089/user 显示经过处理的用户信息
javascript 复制代码
{
  "authorities": [
    "OAUTH2_USER",
    "SCOPE_user:email"
  ],
  "username": "授权返回的用户名"
}

6. 常见问题与扩展

  • 回调地址不匹配:确保 redirect-uri 与注册应用时填写的一致
  • 跨域问题:前端分离项目需配置 CorsFilter
  • 用户信息字段缺失:检查 user-info-uriuser-name-attribute 配置

7. 总结

通过 Spring Security 6OAuth2 Client 模块,开发者可以快速集成主流社交登录功能。本章节案例以 GitHubGitee 为例,展示了从应用注册到用户信息处理的完整流程,适用于需要第三方登录的 Web 应用场景。

后续章节博主将继续扩展支持微信、支付宝、QQ、微博等更多平台,进一步提升用户体验。

如果你在实践过程中有任何疑问或更好的扩展思路,欢迎在评论区留言,最后希望大家 一键三连 给博主一点点鼓励!


相关推荐
考虑考虑1 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯2 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
青石路6 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
Java陈序员8 小时前
企业级!一个基于 Java 开发的开源 AI 应用开发平台!
spring boot·agent·mcp
极光技术熊8 小时前
Spring AI 从入门到精通:构建你的 AI 开发知识体系
后端·github
像我这样帅的人丶你还9 小时前
Java 后端详解(五):Redis 缓存
java·后端·全栈
用户39483951075539 小时前
怎么让我的 Agent 真正"懂"我?——关于记忆、经验学习与预测的一些真实体验
github
plainGeekDev11 小时前
GreenDAO → Room
android·java·kotlin
远航_15 小时前
git submodule
前端·后端·github
杨运交15 小时前
[041][公共模块]分布式唯一ID生成器设计与实现:一款灵活可扩展的雪花算法框架
spring boot