点击上方 Java后端,选择 设为星标
优质文章,及时送达
如何能在自己的网站上接入 QQ 登录功能?这篇文章就是解决这个事情。此文基于OAuth2 协议开发 QQ 联合登录实战过程,在学习本篇内容前您需要提前了解:
-
前后端分离开发模式
-
vue.js 基础语法 比如 axios、事件绑定等相关知识
-
后端开发、数据库等相关基础知识
如果您已经具备了以上所述那我们就开搞吧!
什么是OAuth2
OAuth2.0 是一个开放协议的标准,该标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像、照片、视频等),而在这个过程中无需将用户名和密码提供给第三方应用。实现这一功能是通过提供一个令牌(token),而不是使用用户名和密码来访问他们存放在特定服务提供者的数据。采用令牌(token)的方式可以让用户灵活的对第三方应用授权或者收回权限。
对于大家而言,我们在互联网应用中最常见的 OAuth2 应该就是各种第三方登录了,例如 QQ 授权登录、微信授权登录、微博授权登录、GitHub 授权登录等等
oauth2 的认证流程如图。

OAuth2中有4种授权模式
简化模式适用于纯静态页面应用。所谓纯静态页面应用,也就是应用没有在服务器上执行代码的权限(通常是把代码托管在别人的服务器上),只有前端 JS 代码的控制权。这种场景下,应用是没有持久化存储的能力的。因此,按照 oAuth2.0 的规定,这种应用是拿不到 Refresh Token 的。其整个授权流程如下:
授权码模式:授权码模式适用于有自己的服务器的应用,它是一个一次性的临时凭证,用来换取 access_token 和 refresh_token, 认证服务器提供了一个类似这样的接口:https://www.funtl.com/exchange?code=&client_id=&client_secret=需要传入 code、client_id 以及 client_secret。验证通过后,返回 access_token 和 refresh_token。一旦换取成功,code 立即作废,不能再使用第二次。流程图如下:
密码模式中用户向客户端提供自己的用户名和密码。客户端使用这些信息,向 "服务商提供商" 索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分认证流程如下:
4. 客户端模式: 如果信任关系再进一步,或者调用者是一个后端的模块,没有用户界面的时候,可以使用客户端模式。鉴权服务器直接对客户端进行身份验证,验证通过后,返回 token。认证流程如下:
以上做出了笔者对于 OAuth2.0 协议的理解,关于 OAuth2.0 协议的详细内容在此不扩展了 可访问 腾讯开放平台 https://wiki.connect.qq.com/ 查阅更详细的介绍,本文在此选择使用4中认证模式中的授权码模式进行案例开发,这个模式也是最安全最常用的模式.
2. 开发前阅读文档
本篇内容主要完成网站接入以下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登陆的应用的客户端密匙
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. 在腾讯开放平台中创建应用
-
网站地址这里要填写一个标准的域名地址(可以填一个假的域名)
-
回调地址 这里是腾讯服务器将参数回传到你项目中的接口
-
提供方 填写网站后缀即可
-
备案号 笔者写上qq邮箱也没问题



-
xiaomishop 就是你创建的应用名称
-
appId: 就是你创建的应用的id
-
appkey: 就是你创建的应用的密钥
-
回调地址:后面开发用到这个地址,这里是可以修改的
4. 编码与案例实现
mvn install:install-file -Dfile=F:/Sdk4J.jar -DgroupId=com.sdk4j -DartifactId=sdk4j -Dversion=1.0 -Dpackaging=jar
-
-Dfile= 指定需要install的jar包所在路径
<dependency>
<groupId>com.sdk4j</groupId>
<artifactId>sdk4j</artifactId>
<version>1.0</version>
</dependency>
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 参数可以查看官网文档,这里授权范围 只需要获取到用户信息即可
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;
}
点击按钮发起请求的代码如下:
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 发起网络请求的工具方法,基础语法查阅文档学习啦!!

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
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);
}
res.sendRedirect("http://127.0.0.1:8080/#/login?token="+token)
这一步中也许很多朋友不理解,思路是这样的,因为我们的 sdk 是服务端的 api 请求形式,在获取到用户信息之后 服务端 api 是无法通知前端登录页面做如何调转,这里的重定向就是通知前端界面调转的 ,可以看到携带了 token 参数,当前端地址重定向后地址栏中会携带这个 token,前端需要获取到这个 token,再发送请求根据这个 token 判断对应的用户是否绑定手机号,如果未绑定手机号则 前端需要调转至用户绑定手机号界面完成绑定。
至此本篇文章向大家展示了基于Oauth2.0协议完成 QQ 联合登录的案例,很多步骤需要朋友自己去思考和琢磨。
Java后端交流群已成立
公众号运营至今,离不开小伙伴们的支持。为了给小伙伴们提供一个互相交流的平台,特地开通了官方交流群。扫描下方二维码备注 进群 或者关注公众号 Java后端 后获取进群通道。

推 荐 阅 读 1. 抓包神器:Charles 2. Spring Boot 打包上传至 Docker 仓库? 3. 2W 字详解设计模式 4. 连夜撸了一个简易聊天室 5. 推荐一款 Java 对象映射神器 ![]()
本文分享自微信公众号 - Java后端(web_resource)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。