SpringBoot 原生实现第三方登录 | 不借助第三方依赖包

简介: SpringBoot 原生实现第三方登录 | 不借助第三方依赖包

昨晚写了一篇关于 Oauth 2 的文章,今天就打算用它来实现一个第三方登录的案例。今日是实操啦~

但其实在此之前,我还写过 SpringBoot 整合 JustAuth 实现第三方登录 | gitee登录,但那次是借助 JustAuth 这个第三方包来实现的。

那我们如果自己实现该是如何勒?

一起来看看吧,其实没有你想象的那么难~

建议:

1、先阅读阅读关于 Oauth 2 的文章,更好的理解流程。

2、如果想一步到位,可以看看SpringBoot 整合 JustAuth 实现第三方登录 | gitee登录 这篇

大都数采取授权码模式的应用,在我们的应用中实现第三方登录时,大都一样的。很多共同的特性。

一、时序图

image.png

代码的实现,也是按照这些步骤所写的~

二、实现效果

image.png

补充说明:我是之前登录过了,所以没弹出那个认证授权页面,大家测试的时候,无痕测试就可以看出来啦。

授权页面如下:

image.png

三、Gitee第三方登录案例

项目的话,就创建一个普通的Springboot 项目即可,都是些常规依赖~

3.1、准备工作

在编写代码之前,记得先去Gitee创建一个第三方应用

点击个人头像-->设置-->侧边栏找到数据管理-->第三方应用-->创建一个第三方应用

image.png

上面的Client IDClient Secret待会也是要用到的。

主要填写的就是应用回调地址,这是在认证成功后,会调用的地址。

项目的整体结构

image.png

相关依赖

 <parent>
     <artifactId>spring-boot-dependencies</artifactId>
     <groupId>org.springframework.boot</groupId>
     <version>2.5.2</version>
 </parent>
 ​
 <properties>
     <maven.compiler.source>8</maven.compiler.source>
     <maven.compiler.target>8</maven.compiler.target>
 </properties>
 ​
 <dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-configuration-processor</artifactId>
         <optional>true</optional>
     </dependency>
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
     </dependency>
     <dependency>
         <groupId>cn.hutool</groupId>
         <artifactId>hutool-all</artifactId>
         <version>5.7.22</version>
     </dependency>
     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>fastjson</artifactId>
         <version>1.2.79</version>
     </dependency>
 </dependencies>

配置文件

 erver:
   port: 8089
 spring:
   application:
     name: springboot-thirdly-login
 gitee:
   client-id: 52ac7765xxxxx10b6c539b2c9d402
   client-secret: 1198d5xxd8b0627cxxcd09cc818
   redirect-uri: http://127.0.0.1:8089/oauth/gitee/callback
 /**
  * @description:
  * @author: Ning Zaichun
  * @date: 2022年08月28日 11:15
  */
 @Data
 @Component
 @ConfigurationProperties(prefix = "gitee")
 public class GiteeProperties {
 ​
     private String clientId;
 ​
     private String clientSecret;
 ​
     private String redirectUri;
 }
 /**
  * @description:
  * @author: Ning Zaichun
  * @date: 2022年08月28日 11:27
  */
 public class ThirdlyLoginTypeConstant {
     public final static String  GITEE="gitee";
     public final static String  GITEE_URL="https://gitee.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code";
     public final static String  GITEE_OAUTH_TOKEN_URL="https://gitee.com/oauth/token";
 }
 ​

3.2、service

 /**
  * @description:
  * @author: Ning zaichun
  * @date: 2022年08月28日 12:42
  */
 public interface OauthService {
 ​
     /**
      * 根据传入的所选择的第三方登录类型,返回认证的url
      * @param loginType 第三方登录类型
      * @return
      */
     String choiceLoginType(String loginType);
 ​
     /**
      *
      * 根据用户的授权码和登录类型,获取第三方应用的 access_token
      * @param loginType 第三方登录类型
      * @param code 用户授权码
      * @return
      */
     String getOauthToken(String loginType, String code);
 ​
 ​
     /**
      * 获取授权的用户信息
      * @param loginType 第三方登录类型
      * @param accessToken 认证通过的令牌
      * @return
      */
     String getUserInfo(String loginType,String accessToken);
 }
 /**
  * @description:
  * @author: Ning Zaichun
  * @date: 2022年08月28日 12:42
  */
 @Service
 public class OauthServiceImpl implements OauthService {
 ​
     @Autowired
     GiteeProperties giteeProperties;
 ​
     @Override
     public String choiceLoginType(String loginType) {
         String url = "";
         if (ThirdlyLoginTypeConstant.GITEE.equals(loginType)) {
             url = ThirdlyLoginTypeConstant.GITEE_URL
                     .replace("{client_id}", giteeProperties.getClientId())
                     .replace("{redirect_uri}", giteeProperties.getRedirectUri());
         }
         return url;
     }
 ​
     @Override
     public String getOauthToken(String loginType, String code) {
         Map<String, Object> map = new HashMap<>();
         String result = "";
         if (ThirdlyLoginTypeConstant.GITEE.equals(loginType)) {
             String url = ThirdlyLoginTypeConstant.GITEE_OAUTH_TOKEN_URL;
             map.put("grant_type", "authorization_code");
             map.put("code", code);
             map.put("client_id", giteeProperties.getClientId());
             map.put("client_secret", giteeProperties.getClientSecret());
             map.put("redirect_uri", giteeProperties.getRedirectUri());
             //发送get请求并接收响应数据
             result = HttpUtil.createPost(url).form(map).execute().body();
         }
         return result;
     }
 ​
     @Override
     public String getUserInfo(String loginType, String accessToken) {
         String userInfo = "";
         if (ThirdlyLoginTypeConstant.GITEE.equals(loginType)) {
             String userInfoUrl = "https://gitee.com/api/v5/user?access_token=" + accessToken;
             userInfo = HttpUtil.createGet(userInfoUrl).execute().body();
         }
         return userInfo;
     }
 }

3、controller

 /**
  * @description:
  * @author: Ning zaichun
  * @date: 2022年08月28日 11:12
  */
 @Slf4j
 @RequestMapping("/oauth")
 @RestController
 public class OauthController {
 ​
 ​
     @Autowired
     OauthService oauthService;
 ​
     /**
      * 1、用户点击使用 Gitee 作为第三方登录,后台重定向至gitee认证页面
      *
      * @param loginType
      * @param response
      * @throws IOException
      */
     @GetMapping("/login/{loginType}")
     public void thirdlyLogin(@PathVariable("loginType") String loginType, HttpServletResponse response) throws IOException {
         String url = oauthService.choiceLoginType(loginType);
         log.info(url);
         response.sendRedirect(url);
     }
 ​
 ​
     /**
      * 回调地址 这里就对应着我们在gitee创建第三方应用时填写的回调地址 这里会传回一个 code ,这个code 就是用户认证通过的授权码
      
      * http://127.0.0.1:8089/oauth/gitee/callback?code=xxxxebe2a67ba13xxxx925615aa89041
      * 其中 code 为用户授权码,由gitee授权服务器调用回调地址携带而来
      *
      * @param loginType
      * @param code
      * @param state 它并非是必填项,gitee调用回调地址时,其实没有携带这个参数,但是在oauth中有讲到,当时就写上去了。
      * @return
      */
     @ResponseBody
     @GetMapping("/{loginType}/callback")
     public String redirectUri(@PathVariable("loginType") String loginType, String code, String state) {
         log.info("code==>{}", code);
         //1、拿到这个code之后,我们要再向 gitee 服务起请求,获取 access_token 请注意这是一个post 请求
         // https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}
         String result = oauthService.getOauthToken(loginType, code);
         ThirdlyResult thirdlyResult = (ThirdlyResult) JSON.parseObject(result, ThirdlyResult.class);
         /**
          * {
          * "access_token":"f7d851b2cdxx1fd491b",
          * "token_type":"bearer",
          * "expires_in":86400,
          * "refresh_token":"9f3098c7a8be09cd15xxcc38fb3dxxxb8e40f0800ced8",
          * "scope":"user_info",
          * "created_at":1661659283
          * }
          */
 ​
         /**
          * 我这里只是测试获取用户信息的请求 
          * 如果需要实现登录的话,自己加上业务逻辑即可
          */
         // 2、拿到 access_token 以后发送一个get 请求,获取用户信息
         String userInfo = oauthService.getUserInfo(loginType, thirdlyResult.getAccessToken());
         return userInfo;
     }
 }

在请求获取 access_token的接口会返回的数据格式,方便转换,就写了一下~

 /**
  * @description:
  * @author: Ning zaichun
  * @date: 2022年08月28日 12:18
  */
 @Data
 public class ThirdlyResult {
 ​
     /**
      * {
      * "access_token":"f7xxxb71fd491b",
      * "token_type":"bearer",
      * "expires_in":86400,
      * "refresh_token":"9f3098c7a8be09cdxxxxx53a2f69dccxxxx8e40f0800ced8",
      * "scope":"user_info",
      * "created_at":1661659283
      * }
      */
     private String accessToken;
 ​
     private String tokenType;
 ​
     private Long expiresIn;
 ​
     private String refreshToken;
 ​
     private String scope;
 ​
     private String createAt;
 }

3.4、小结

其实实现第三方登录其实也没有想象的那么难,把思路一步一步理清楚就可以了。

我也相信大家在看完文章后已经能够手动的实现第三方登录啦吧~

后记

尝试做一些自己喜欢的事情吧~

今天结束啦,周末也要结束啦~

放个收藏老久的可达鸭吧~

image.png

目录
相关文章
|
10月前
|
Java Maven 微服务
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的 maven 依赖
在项目中使用Swagger2工具时,需导入Maven依赖。尽管官方最高版本为2.8.0,但其展示效果不够理想且稳定性欠佳。实际开发中常用2.2.2版本,因其稳定且界面友好。以下是围绕2.2.2版本的Maven依赖配置,包括`springfox-swagger2`和`springfox-swagger-ui`两个模块。
457 0
|
XML Java 应用服务中间件
SpringBoot项目打war包流程
本文介绍了将Spring Boot项目改造为WAR包并部署到外部Tomcat服务器的步骤。主要内容包括:1) 修改pom.xml中的打包方式为WAR;2) 排除Spring Boot内置的Tomcat依赖;3) 添加Servlet API依赖;4) 改造启动类以支持WAR部署;5) 打包和部署。通过这些步骤,可以轻松地将Spring Boot应用转换为适合外部Tomcat服务器的WAR包。
731 64
SpringBoot项目打war包流程
|
11月前
|
Java Maven 开发者
编写SpringBoot的自定义starter包
通过本文的介绍,我们详细讲解了如何创建一个Spring Boot自定义Starter包,包括自动配置类、配置属性类、`spring.factories`文件的创建和配置。通过自定义Starter,可以有效地复用公共配置和组件,提高开发效率。希望本文能帮助您更好地理解和应用Spring Boot自定义Starter,在实际项目中灵活使用这一强大的功能。
974 17
|
11月前
|
Java 应用服务中间件 Maven
SpringBoot项目打包成war包
通过上述步骤,我们成功地将一个Spring Boot应用打包成WAR文件,并部署到外部的Tomcat服务器中。这种方式适用于需要与传统Servlet容器集成的场景。
1338 8
|
10月前
|
缓存 Java 应用服务中间件
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——依赖导入和Thymeleaf相关配置
在Spring Boot中使用Thymeleaf模板,需引入依赖`spring-boot-starter-thymeleaf`,并在HTML页面标签中声明`xmlns:th=&quot;http://www.thymeleaf.org&quot;`。此外,Thymeleaf默认开启页面缓存,开发时建议关闭缓存以实时查看更新效果,配置方式为`spring.thymeleaf.cache: false`。这可避免因缓存导致页面未及时刷新的问题。
418 0
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
1074 1
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
|
数据可视化 Java 应用服务中间件
springboot打war包,成功部署
这篇文章介绍了如何将Spring Boot项目打包成WAR文件,并成功部署到Tomcat服务器的详细步骤。
1444 0
springboot打war包,成功部署
|
关系型数据库 MySQL Java
基于SpringBoot+Vue旅游管理系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】
基于SpringBoot+Vue旅游管理系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】
269 0
基于SpringBoot+Vue旅游管理系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】
|
安全 JavaScript Java
基于SpringBoot+Vue论坛管理系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】
基于SpringBoot+Vue论坛管理系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】
191 0
基于SpringBoot+Vue论坛管理系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】
|
Java 数据安全/隐私保护 Python
基于SpringBoot+Vue简历系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】(2)
基于SpringBoot+Vue简历系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】
159 0
基于SpringBoot+Vue简历系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】(2)

热门文章

最新文章