基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

2年前 (2022) 程序员胖胖胖虎阿
198 0 0

点击上方 Java后端选择 设为星标

优质文章,及时送达


如何能在自己的网站上接入 QQ 登录功能?这篇文章就是解决这个事情。此文基于OAuth2 协议开发 QQ 联合登录实战过程,在学习本篇内容前您需要提前了解:

  1. 前后端分离开发模式

  2. vue.js 基础语法 比如 axios、事件绑定等相关知识

  3. 后端开发、数据库等相关基础知识

如果您已经具备了以上所述那我们就开搞吧!

1.
什么是OAuth2

OAuth2.0 是一个开放协议的标准,该标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像、照片、视频等),而在这个过程中无需将用户名和密码提供给第三方应用。实现这一功能是通过提供一个令牌(token),而不是使用用户名和密码来访问他们存放在特定服务提供者的数据。采用令牌(token)的方式可以让用户灵活的对第三方应用授权或者收回权限。

对于大家而言,我们在互联网应用中最常见的 OAuth2 应该就是各种第三方登录了,例如 QQ 授权登录、微信授权登录、微博授权登录、GitHub 授权登录等等
oauth2 的认证流程如图。

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

OAuth2中有4种授权模式

1. 简化模式:
简化模式适用于纯静态页面应用。所谓纯静态页面应用,也就是应用没有在服务器上执行代码的权限(通常是把代码托管在别人的服务器上),只有前端 JS 代码的控制权。这种场景下,应用是没有持久化存储的能力的。因此,按照 oAuth2.0 的规定,这种应用是拿不到 Refresh Token 的。其整个授权流程如下:

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

2. 
授权码模式:授权码模式适用于有自己的服务器的应用,它是一个一次性的临时凭证,用来换取 access_token 和 refresh_token, 认证服务器提供了一个类似这样的接口:https://www.funtl.com/exchange?code=&client_id=&client_secret=需要传入 code、client_id 以及 client_secret。验证通过后,返回 access_token 和 refresh_token。一旦换取成功,code 立即作废,不能再使用第二次。流程图如下:

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

3. 密码模式: 
密码模式中用户向客户端提供自己的用户名和密码。客户端使用这些信息,向 "服务商提供商" 索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分认证流程如下:

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

4. 客户端模式: 如果信任关系再进一步,或者调用者是一个后端的模块,没有用户界面的时候,可以使用客户端模式。鉴权服务器直接对客户端进行身份验证,验证通过后,返回 token。认证流程如下:

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

以上做出了笔者对于 OAuth2.0 协议的理解,关于 OAuth2.0 协议的详细内容在此不扩展了 可访问 腾讯开放平台 https://wiki.connect.qq.com/ 查阅更详细的介绍,本文在此选择使用4中认证模式中的授权码模式进行案例开发,这个模式也是最安全最常用的模式.

2. 开发前阅读文档

访问腾讯开放平台官网点击文档栏 会有以下内容显示

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战



本篇内容主要完成网站接入以下4个步骤就是网站接入需要完成的4个步骤

1.生成授权链接,获取 code 

GET https://graph.qq.com/oauth2.0/authorize?response_type=code& client_id=101420900&redirect_uri=http://127.0.0.1:10011/user/qqAuthenticationFallback& state=1234656
  • client_id 为用户在腾讯开放平台填写的需要qq登陆的应用的 客户端id
  • redirect_uri 授权回调的地址,需要在腾讯开放平台上填写
  • state:参数可随意

2.根据 code 获取 access_token 

GET https://graph.qq.com/oauth2.0/token?grant_type=authorization_code& client_id=101420900&client_secret=bd56a336f6ac49a65005595c2a41201a&code=E28F27AFC3D8A17B75F05E9661FB933E &redirect_uri=http://127.0.0.1:8764/mobile/qqLoginCallback
  • client_id 为用户在腾讯开放平台填写的需要qq登陆的应用的 客户端id
  • redirect_uri 授权回调的地址,需要在腾讯开放平台上填写
  • code:为授权链接返回的标识
  • client_secret:为需要qq登陆的应用的客户端密匙
4. 根据 access_token 获取 openId (qq登陆) 
GET https://graph.qq.com/oauth2.0/me?access_token=CF8775A510EA68ED8576C9F675B42862
  • access_token:第2步返回的令牌

5. 再由openId和access_token向腾讯服务器换取用户信息 

GET https://graph.qq.com/user/get_user_info? access_token=CF8775A510EA68ED8576C9F675B42862& oauth_consumer_key=12345& openid=537F314752DA3A491B4F66C04D6AD9FF
  • access_token :第2步返回的令牌
  • oauth_consumer_key:需要qq登陆的应用id
  • openId:为上一步的返回值

3. 在腾讯开放平台中创建应用

了解看懂了网站接入开发的4个步骤之后那我们就进入开发准备吧!网站上的文档说的很清晰了我们先要在开放平台上创建应用后才能接入开发,以下是大致的应用创建过程
1. 访问腾讯开放平台点击QQ开放平台如图:

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

2. 选择网站应用点击创建应用

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

3. 填写和完善网站基本资料信息

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战



基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

  • 网站地址这里要填写一个标准的域名地址(可以填一个假的域名)
  • 回调地址 这里是腾讯服务器将参数回传到你项目中的接口
  • 提供方 填写网站后缀即可
  • 备案号 笔者写上qq邮箱也没问题
填写好之后提交,提交后应用不会立即生效可用 应用是需要审核的审核时间一周内完成!应用创建好之后登录腾讯开放平台点击应用管理查看应用审核状态如图:
基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战
点击查看应用 会显示如下图:
基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战
基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战
  • xiaomishop 就是你创建的应用名称
  • appId: 就是你创建的应用的id
  • appkey: 就是你创建的应用的密钥
  • 回调地址:后面开发用到这个地址,这里是可以修改的
在腾讯开放平台创建好应用之后就可以正式进入写代码阶段

4. 编码与案例实现

在阅读官方文档后我们知道认证和登录的那4个步骤其实就是自己的网站和腾讯服务器之间的http协议交互,所以我们需要在Java代码中发送http请求,在此我们需要在腾讯平台上下载 官方的 java 版的 sdk工具包,或者从笔者网盘中下载 网盘地址为:https://pan.baidu.com/s/1Cvg4tAiSPEzRAIbnwsPeEg  提取码:zo0j
在此声明本篇文章实战的案例的完整源码是不能对外开放,所以需要读者详细阅读完这篇案例文章了解本篇文章采用的方法和思路后自己动手写出属于自己的案例,本篇文章旨在介绍 QQ 联合登录方式中的一种思路和实现方式,重在思路,实现并不难。
闲话不多说了,目前笔者有一个前后端分离的项目,前端项目使用 vue.js ,后端项目是一个 Spring Boot 项目,在这个项目中已经实现了用户手机号登录(新用户自动注册),登录成功后,后端随机生成的 token,并且 token 作为 key,用户 id 作为 value 存入 redis 中,并把 token 返回给前端。现在我们需要再开发出 QQ 登录功能,用户登录时可以选择 QQ 登录也可以使用手机号获取验证码登录。
思考一个问题?
同一个用户使用不同的账号登录同一个网站,那网站如何识别这两种不同的账号是同一个人的账号呢?其实不难想到 ,使用一个中间值关联两种账号。在 QQ 联合登录的4个步骤中我们知道 QQ 登录成功后可以获取到一个唯一的 openId,所以我们需要拿这个 openId 来绑定使用手机号登录的用户,那具体如何绑定呢?首先我们需要修改数据库中现有的用户表,添加一个字段表示第三方登录成功后获取到的 openId,用户表如下。

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战

大致思路以下:
用户点击使用 QQ 登录,登录成功获取到 openId 后,根据这个 openId 查询用户表是否存在相对应的用户,如果有就返回该用户即可,如果没有那么需要用户绑定一个手机号,如果这个手机号是已经注册的用户,那把 openId 存入到已有账户数据中即可,如果用户表中并不存在这个手机号创建的用户则根据这个手机号和 openId 创建一个账户。
思路明白之后我们就可以开始写后端代码了,此处只给出必要的代码块希望读者能理解本文之后自己根据自己项目的业务设计出想要的效果,因为本项目是使用maven管理jar包依赖,所以需要把上文的sdk install 至本地maven仓库使用命令:
mvn install:install-file -Dfile=F:/Sdk4J.jar -DgroupId=com.sdk4j -DartifactId=sdk4j -Dversion=1.0 -Dpackaging=jar
  • -Dfile= 指定需要install的jar包所在路径
执行成功后在SpringBoot项目的pom.xml文件添加如下依赖:
<dependency>
    <groupId>com.sdk4j</groupId>
    <artifactId>sdk4j</artifactId>
    <version>1.0</version>
</dependency>
在项目 resources 目录下新建文件 qqconnectconfig.properties 文件内容如下:
app_ID = #客户端appid
app_KEY = #appkey 密匙
redirect_URI = #回调地址
scope = get_user_info #授权范围
baseURL = https://graph.qq.com/
getUserInfoURL = https://graph.qq.com/user/get_user_info
accessTokenURL = https://graph.qq.com/oauth2.0/token
authorizeURL = https://graph.qq.com/oauth2.0/authorize
getOpenIDURL = https://graph.qq.com/oauth2.0/me
addTopicURL = https://graph.qq.com/shuoshuo/add_topic
addBlogURL = https://graph.qq.com/blog/add_one_blog
addAlbumURL = https://graph.qq.com/photo/add_album
uploadPicURL = https://graph.qq.com/photo/upload_pic
listAlbumURL = https://graph.qq.com/photo/list_album
addShareURL = https://graph.qq.com/share/add_share
checkPageFansURL = https://graph.qq.com/user/check_page_fans
addTURL = https://graph.qq.com/t/add_t
addPicTURL = https://graph.qq.com/t/add_pic_t
delTURL = https://graph.qq.com/t/del_t
getWeiboUserInfoURL = https://graph.qq.com/user/get_info
getWeiboOtherUserInfoURL = https://graph.qq.com/user/get_other_info
getFansListURL = https://graph.qq.com/relation/get_fanslist
getIdolsListURL = https://graph.qq.com/relation/get_idollist
addIdolURL = https://graph.qq.com/relation/add_idol
delIdolURL = https://graph.qq.com/relation/del_idol
getTenpayAddrURL = https://graph.qq.com/cft_info/get_tenpay_addr
getRepostListURL = https://graph.qq.com/t/get_repost_list
version = 2.0.0.0
  • app_ID 就是在腾讯开放中心创建成功的应用id
  • app_KEY 就是在腾讯开放中心创建成功的应用密钥
  • redirect_URI 就是在腾讯开放中心创建应用的授权成功后调地址
  • scope 参数可以查看官网文档,这里授权范围 只需要获取到用户信息即可
其余参数都无需更改
接下我们按照上文中认证和授权的4个步骤一步一步的写代码

1. 生成授权链接

后端代码
//qq联合登陆第一步
//controller 实现
@GetMapping("getAuthenticationUrl")
public Map<String,Object>getAuthenticationUrl(HttpServletRequest res) throws Exception {
    return userService.getAuthenticationUrl(type,res);
}
--------------------------------
//service层实现 返回String授权地址给前端即可
@Override
public Map<String, Object> getAuthenticationUrl(HttpServletRequest res) {
    return BaseResponse.Result(EnumStatus.OK,result);
},

public String getAuthenticationUrl(HttpServletRequest request) throws QQConnectException {
    String authorizeURL = new Oauth().getAuthorizeURL(request);
    return authorizeURL;
}
前端vue.js实现,我们需要在登录页添加一个qq登录的按钮图标,用户点击时调用下文ThirdLogin()函数发起请求,效果如图:

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战



点击按钮发起请求的代码如下:
ThirdLogin(){
  this.axios.get(getAuthenticationUrl).then(res=>{
    if(res.data.code===200){
    // 浏览器窗口打开后端返回的授权地址
    window.location.href= res.data.data
    }
    console.log(res)
  })
},
  • getAuthenticationUrl==http://127.0.0.1:10011/api/userservice/user/getAuthenticationUrl就是上文定义的接口

  • 这里的this.axios就是vue.js 发起网络请求的工具方法,基础语法查阅文档学习啦!!
启动前后端项目,点击qq登录按钮 此时第一步成功完成的效果图如下:
基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战
可以看到返回的授权地址如下:
https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=101834111&redirect_uri=http://127.0.0.1:10011/user/qqAuthenticationFallback&response_type=code&state=69d3bfdc448eec21026cb500be570f93&scope=get_user_info
注意这个redirect_uri 地址

2. 编写回调地址接口,根据code 获取access_token 再根据access_token 获取到用户的信息。

@ResponseBody
@GetMapping("qqAuthenticationFallback")
public void qqAuthenticationFallback(HttpServletRequest request,HttpServletResponse res) throws QQConnectException, IOException {
    // 1.回调地址中会拼接着 code
    String code = request.getParameter("code");
    log.info("code="+code);
    // 2.通过 code 获取授权码,
    // AccessToken accessTokenObj = new Oauth().getAccessTokenByRequest(request);
   // 此方法不行啊 只能使用httpClient 发送请求获取数据
    String url="https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id="+appId+"&client_secret="+appKey+"&code="+code+"&redirect_uri="+redirectURI;
    HttpGet httpGet = new HttpGet(url);
    CloseableHttpClient client= HttpClients.createDefault();
    CloseableHttpResponse response = client.execute(httpGet);
    HttpEntity entity = response.getEntity();
    byte[] bytes = EntityUtils.toByteArray(entity);
    String str = new String(bytes, "utf-8");
    String[] split = str.split("&");
    String[] split1 = split[0].split("=");
    // 3.再根据授权码获取到 access_token
    OpenID openID = new OpenID(split1[1]);
    String accessToken=split1[1];
    log.info("accessToken="+accessToken);
    String userOpenID = openID.getUserOpenID();
    // 4.通过令牌获取用户的 openId
    log.info("openId="+userOpenID);
    // 以上4步已经实现了qq联合登陆
    //5.根据openId和accessToken从获取用户信息
    String token = userService.ThirdLogin(accessToken, userOpenID);
    res.sendRedirect("http://127.0.0.1:8080/#/login?token="+token);
}
这里的 userService.ThirdLosing() 方法实现 可以发送 httpClient 请求获取到用户的信息(也就是你的 QQ 账号信息),地址为上文4个步骤中的最后一步的请求地址,除了获取到用户信息之外,还要完成上文中我们提到的思路 即账号之间的绑定和创建 这里就不再赘述了,每个人项目都不同,要自己多思考哦。
res.sendRedirect("http://127.0.0.1:8080/#/login?token="+token)

这一步中也许很多朋友不理解,思路是这样的,因为我们的 sdk 是服务端的 api 请求形式,在获取到用户信息之后 服务端 api 是无法通知前端登录页面做如何调转,这里的重定向就是通知前端界面调转的 ,可以看到携带了 token 参数,当前端地址重定向后地址栏中会携带这个 token,前端需要获取到这个 token,再发送请求根据这个 token 判断对应的用户是否绑定手机号,如果未绑定手机号则 前端需要调转至用户绑定手机号界面完成绑定。

至此本篇文章向大家展示了基于Oauth2.0协议完成 QQ 联合登录的案例,很多步骤需要朋友自己去思考和琢磨。


   
   
   
Java后端交流群已成立
公众号运营至今,离不开小伙伴们的支持。为了给小伙伴们提供一个互相交流的平台,特地开通了官方交流群。扫描下方二维码备注 进群 或者关注公众号 Java后端 后获取进群通道。

基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战


    
    
    
     
         
         
         
读 
1. 抓包神器:Charles
2. Spring Boot 打包上传至 Docker 仓库?
3. 2W 字详解设计模式
4. 连夜撸了一个简易聊天室
5. 推荐一款 Java 对象映射神器
基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战


本文分享自微信公众号 - Java后端(web_resource)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

版权声明:程序员胖胖胖虎阿 发表于 2022年9月28日 下午1:00。
转载请注明:基于 Spring Boot + Vue.js + MySQL 的 QQ 登陆实战 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...