使用Spring Security快速实现Oauth2客户端配置

grtsinry43
12/15/2024
93 views
预计阅读时长 13 分钟

在Spring的强大生态中,我们很多时候只需要简单的配置就可以完成想要的需求。在Grtblog中,我使用了其提供的能力快速完成了Oauth2Client配置,实现了第三方账号的快速注册以及登录,更便于用户快速获得账号参与评论,提升用户体验。

安装依赖

pom.xml中添加相关的依赖并同步即可

XML
1<dependency>
2    <groupId>org.springframework.boot</groupId>
3    <artifactId>spring-boot-starter-security</artifactId>
4</dependency>
5<dependency>
6    <groupId>org.springframework.boot</groupId>
7    <artifactId>spring-boot-starter-oauth2-client</artifactId>
8</dependency>

创建流程

相关配置

得益于依赖的强大封装,我们只需要在application.yml中配置好Oauth应用的信息即可

我们这里以Github和Google为例:

YML
1spring:
2  security:
3    oauth2:
4      client:
5        registration:
6          google:
7            client-id: your_client_id
8            client-secret: your_client_secret
9            scope: profile, email
10            redirect-uri: "https://your_deploy_site/api/v1/login/oauth2/code/google" //回调地址,其默认端点为/login/oauth2/code/google
11            client-name: Google
12          github:
13            client-id: your_client_id
14            client-secret: your_client_secret
15            redirect-uri: "https://your_deploy_site/api/v1/login/oauth2/code/github"
16            scope: user:email
17            client-name: Github
18        provider:
19          google:
20            authorization-uri: https://accounts.google.com/o/oauth2/auth
21            token-uri: https://oauth2.googleapis.com/token
22            user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
23            user-name-attribute: sub
24          github:
25            authorization-uri: https://github.com/login/oauth/authorize
26            token-uri: https://github.com/login/oauth/access_token
27            user-info-uri: https://api.github.com/user
28            user-name-attribute: id

用户信息处理

首先,在Oauth的登录流程中,我们可以通过userInfoEndpoint获得对应的OauthUser对象,也可以执行自己的一些处理,保存或者查找用户信息,因此,我们可以手动继承DefaultOAuth2UserService

JAVA
1import com.grtsinry43.grtblog.entity.User;
2import com.grtsinry43.grtblog.mapper.UserMapper;
3import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
4import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
5import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
6import org.springframework.security.oauth2.core.user.OAuth2User;
7import org.springframework.stereotype.Service;
8
9/**
10 * @author grtsinry43
11 * @date 2024/11/9 23:00
12 * @description 热爱可抵岁月漫长
13 */
14@Service
15public class CustomOAuth2UserService extends DefaultOAuth2UserService {
16    private final UserMapper userMapper;
17
18    public CustomOAuth2UserService(UserMapper userMapper) {
19        this.userMapper = userMapper;
20    }
21
22
23    @Override
24    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
25        OAuth2User oAuth2User = super.loadUser(userRequest);
26
27        // 在这里,我们便可以对解析的用户做自己的操作
28
29        return oAuth2User;
30    }
31}

自定义的用户信息处理

当我们拿到oauth2user对象后,我们便可以添加自己的相关处理逻辑

例如我们可以拿到用户的邮箱、头像、昵称等等信息,然后验证用户是否存在,不存在则创建,存在则直接查询相关信息

JAVA
1String provider = userRequest.getClientRegistration().getRegistrationId();
2String oauthId = oAuth2User.getAttribute("sub") == null ? oAuth2User.getAttribute("id") + "" : oAuth2User.getAttribute("sub") + "";
3String email = oAuth2User.getAttribute("email");
4String avatar = oAuth2User.getAttribute("avatar_url") == null ? oAuth2User.getAttribute("picture") + "" : oAuth2User.getAttribute("avatar_url") + "";
5
6User user = userMapper.getUserByOAuthProviderAndId(provider, oauthId);
7if (user == null) {
8    user = new User();
9    user.setEmail(email);
10    user.setNickname(oAuth2User.getAttribute("login") == null ? oAuth2User.getAttribute("name") + "" : oAuth2User.getAttribute("login") + "");
11    user.setOauthProvider(provider);
12    user.setAvatar(avatar);
13    user.setOauthId(oauthId);
14    userMapper.insert(user);
15} // 这里如果存在可以在选择性更新

当获取了用户信息并保证其保存至数据库时,我们就可以执行登录完成的处理啦

登录后处理

当我们登录成功后,我们可以手动继承AuthenticationSuccessHandler来实现自己的成功处理(回调)逻辑

这里我采用了jwt进行认证相关逻辑,因此我们可以采用设置cookie的方式将生成的token传递到前端,我们可以这么实现

JAVA
1import com.grtsinry43.grtblog.util.JwtUtil;
2import jakarta.servlet.ServletException;
3import jakarta.servlet.http.Cookie;
4import jakarta.servlet.http.HttpServletRequest;
5import jakarta.servlet.http.HttpServletResponse;
6import org.springframework.security.core.Authentication;
7import org.springframework.security.oauth2.core.user.OAuth2User;
8import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
9import org.springframework.stereotype.Component;
10
11import java.io.IOException;
12
13/**
14 * @author grtsinry43
15 * @date 2024/11/25 19:37
16 * @description 热爱可抵岁月漫长
17 */
18@Component
19public class OAuth2LoginSuccessHandler implements AuthenticationSuccessHandler {
20
21    @Override
22    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
23        // 获取 redirect_uri 参数
24        String redirectUri = request.getParameter("redirect_uri");
25
26        // 如果没有指定 redirect_uri,设置默认跳转地址
27        if (redirectUri == null || redirectUri.isEmpty()) {
28            redirectUri = "https://blog.grtsinry43.com/";
29        }
30
31        // 获取 principal 对象
32        Object principal = authentication.getPrincipal();
33        String email;
34
35        if (principal instanceof OAuth2User) {
36            email = ((OAuth2User) principal).getAttribute("email");
37        } else if (principal instanceof LoginUserDetails) {
38            email = ((LoginUserDetails) principal).getUser().getEmail();
39        } else {
40            throw new ServletException("Unexpected principal type");
41        }
42
43        // 生成 Token
44        String token = JwtUtil.generateToken(email);
45
46        // 创建 Cookie 来存储 token
47        Cookie cookie = new Cookie("token", token);
48        cookie.setSecure(true);    // 在生产环境中使用 HTTPS 时,启用此选项
49        cookie.setPath("/");       // 设置 Cookie 可在整个站点有效
50        cookie.setMaxAge(3600 * 24 * 7);  // 设置 Cookie 的有效期为 7 天
51
52        // 将 Cookie 添加到响应中
53        response.addCookie(cookie);
54
55        // 重定向到指定的地址
56        response.sendRedirect(redirectUri);
57    }
58}

这样我们便实现了重定向回网页和设置登录信息

前端配置

前端的配置就很简单啦,直接跳转一下网页,选择性携带一下URL编码的当前地址就可以啦

小小总结

对于Oauth2的相关流程,当前端用户点击则转到后端进行处理,换access_token和code等等,在框架拿到用户对象后便可以进行处理,结合cookie将其传到前端保存,由拦截器携带即完成了登录闭环

其实整个过程还是没啥技术含量的,但是毕竟我是主力前端的,这个还是不太了解还是有整理一下的必要的,善用轮子还是大大提高开发效率的

相关推荐

使用 pf4j-spring 实现插件注入和 api 接口动态注册 | 插件系统构建(上)

哪个男孩不想拥有一个自己的插件系统?(x)话说回来,这个我已经计划好久了,不过一直在学其他的东西,刚...

grtsinry43
1/26/2025
40
0
0

折腾记录|使用 Nuxt.js 重写个人主页,使用 SSR 优化 SEO ,实现一些期待已久的效果

在 22 年刚创建个人主页的时候,由于我的技术水平不够,只能用一些 wordpress type...

grtsinry43
9/19/2024
24
0
0

使用 BeautifulSoup 配合请求库实现简单的爬虫程序

事情起源于课内的课程实验作业...因为要求要用爬虫,~~不必说课内讲的一言难尽,更不必说就算讲了我也...

grtsinry43
1/7/2025
67
0
0

使用 Spring Boot + MyBatisPlus 提高效率,简化开发

最近一段时间,由于一些项目的需求,于是被迫用很快的速度学完了 Spring Framework,...

grtsinry43
8/11/2024
36
0
0

学习分享|跨域解决、安卓开发探索、油猴脚本探索

最近学习的一些内容,包括跨域问题及其解决方案,安卓开发的简单探索,OpenAI的api做了个小插...

grtsinry43
6/10/2024
35
0
0
COMMENT 7274088871825117184

发表评论

登录之后评论体验更好哦 ~
支持 Markdown 语法 0 / 3000

在风雨飘摇之中

本站已运行了

一路走来,感谢陪伴与支持

愿我们不负热爱,继续前行

全站通知
更新通知