Spring Security 集成第三方登录
# Spring Security 集成第三方登录
# 1. OAuth2 基础概念
OAuth2 主要有四种授权模式:
- 授权码模式(Authorization Code):常用于 Web 应用程序,安全性高。
- 简化模式(Implicit):用于无后台的前端应用,Token 直接通过 URL 传递。
- 密码模式(Resource Owner Password Credentials):用户直接提供用户名和密码,适用于高信任场景。
- 客户端模式(Client Credentials):应用程序间的授权,适用于无用户参与的场景。
在第三方登录集成中,授权码模式是最常用且推荐的模式。
# 2. Spring Security OAuth2 Client 集成 GitHub 登录
首先,在项目中引入相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
1
2
3
4
2
3
4
GitHub 登录配置(application.yml):
spring:
security:
oauth2:
client:
registration:
github: # 配置 GitHub 登录
client-id: your-github-client-id # 从 GitHub 开发者控制台获取,必须配置
client-secret: your-github-client-secret # 从 GitHub 开发者控制台获取,必须配置
scope: read:user,repo # 请求的权限范围,可根据需求调整
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" # Spring Security 自动处理回调,保持默认即可
client-name: GitHub # 客户端名称,配置成任意可识别的名称
provider:
github:
authorization-uri: https://github.com/login/oauth/authorize # GitHub 授权页面的 URL
token-uri: https://github.com/login/oauth/access_token # 获取访问 Token 的 URL
user-info-uri: https://api.github.com/user # 获取用户信息的 URL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
代码解析:
client-id和client-secret:是应用的标识和密钥,必须从 GitHub 开发者控制台获取。redirect-uri:授权成功后的回调地址,Spring Security 会自动处理,无需手动配置。scope:指定应用请求的权限范围,如读取用户信息、仓库等。
# 3. Spring Security OAuth2 Client 集成 Gitee 登录
Gitee 的配置类似于 GitHub,只需更改部分配置参数。
Gitee 登录配置(application.yml):
spring:
security:
oauth2:
client:
registration:
gitee: # 配置 Gitee 登录
client-id: your-gitee-client-id # 从 Gitee 开发者平台获取,必须配置
client-secret: your-gitee-client-secret # 从 Gitee 开发者平台获取,必须配置
scope: user_info # Gitee 请求的权限范围,通常为获取用户信息
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" # Spring Security 自动处理回调,保持默认即可
client-name: Gitee # 客户端名称,可自定义
provider:
gitee:
authorization-uri: https://gitee.com/oauth/authorize # Gitee 授权页面的 URL
token-uri: https://gitee.com/oauth/token # 获取访问 Token 的 URL
user-info-uri: https://gitee.com/api/v5/user # 获取用户信息的 URL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
配置要点:
authorization-uri和token-uri:分别是 Gitee 的授权地址和 Token 获取地址,必须正确配置。user-info-uri:用于获取 Gitee 用户的详细信息。
# 4. 定义用户实体类并保存到数据库
为了将获取的用户信息保存到数据库中,我们需要创建一个实体类,并使用 JPA 或 MyBatis 进行持久化操作。
用户实体类示例(User.java):
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 用户在数据库中的唯一标识
private String username; // 用户名
private String email; // 用户邮箱
private String avatarUrl; // 用户头像 URL
private String provider; // 第三方平台名称,如 "github" 或 "gitee"
private String providerId; // 第三方平台的用户ID
// 省略 Getter 和 Setter 方法
// 构造函数
public User() {}
public User(String username, String email, String avatarUrl, String provider, String providerId) {
this.username = username;
this.email = email;
this.avatarUrl = avatarUrl;
this.provider = provider;
this.providerId = providerId;
}
}
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
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 Data JPA):
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByProviderAndProviderId(String provider, String providerId);
}
1
2
3
4
5
2
3
4
5
# 5. 自定义 OAuth2 登录逻辑并保存用户信息
我们可以自定义 OAuth2UserService 来实现用户信息的获取和保存。
自定义用户服务(实现 OAuth2UserService 接口):
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.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Autowired
private UserRepository userRepository;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) {
OAuth2User oauth2User = new DefaultOAuth2UserService().loadUser(userRequest);
// 获取第三方平台的用户信息
String provider = userRequest.getClientRegistration().getRegistrationId(); // 如 "github" 或 "gitee"
String providerId = oauth2User.getName(); // 第三方平台的用户ID
String username = oauth2User.getAttribute("login"); // 用户名(取决于具体平台,GitHub 为 "login")
String email = oauth2User.getAttribute("email"); // 邮箱
String avatarUrl = oauth2User.getAttribute("avatar_url"); // 头像 URL
// 检查用户是否已存在于数据库
User user = userRepository.findByProviderAndProviderId(provider, providerId);
if (user == null) {
// 如果用户不存在,则保存用户信息到数据库
user = new User(username, email, avatarUrl, provider, providerId);
userRepository.save(user);
}
return oauth2User; // 返回 OAuth2User 对象
}
}
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
35
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
35
关键点解析:
userRequest.getClientRegistration().getRegistrationId():获取当前登录的平台,如 "github" 或 "gitee"。oauth2User.getAttribute("login"):获取平台的用户信息,不同平台的字段名可能不同,需要根据平台文档确定。- 用户信息持久化:使用 JPA 将用户信息保存到数据库中,支持后续操作。
# 6. OAuth2 登录的完整流程
完整流程如下:
- 用户点击第三方登录按钮,重定向到第三方授权页面(如 GitHub/Gitee)。
- 用户同意授权后,第三方返回授权码给应用。
- 应用使用授权码请求访问 Token。
- 通过访问 Token 获取用户信息,并将其注入到 Spring Security 上下文中。
- 将获取的用户信息保存到数据库。
- 用户登录成功,可以访问受保护的资源。
总结
通过结合 Spring Security 和 JPA,我们不仅实现了第三方登录,还能将用户信息持久化到数据库中,方便后续管理。在集成过程中,关注关键配置参数和自定义用户服务逻辑,可以确保集成顺利进行。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08