如何能在自己的網站上接入 QQ 登錄功能?這篇文章就是解決這個事情。此文基於OAuth2 協議開發 QQ 聯合登錄實戰過程,在學習本篇內容前您需要提前了解:
前後端分離開發模式
vue.js 基礎語法 比如 axios、事件綁定等相關知識
後端開發、資料庫等相關基礎知識
如果您已經具備了以上所述那我們就開搞吧!
OAuth2.0 是一個開放協議的標準,該標準允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密資源(如頭像、照片、視頻等),而在這個過程中無需將用戶名和密碼提供給第三方應用。實現這一功能是通過提供一個令牌(token),而不是使用用戶名和密碼來訪問他們存放在特定服務提供者的數據。採用令牌(token)的方式可以讓用戶靈活的對第三方應用授權或者收回權限。
對於大家而言,我們在網際網路應用中最常見的 OAuth2 應該就是各種第三方登錄了,例如 QQ 授權登錄、微信授權登錄、微博授權登錄、GitHub 授權登錄等等
oauth2 的認證流程如圖。
OAuth2中有4種授權模式
1. 簡化模式:簡化模式適用於純靜態頁面應用。所謂純靜態頁面應用,也就是應用沒有在伺服器上執行代碼的權限(通常是把代碼託管在別人的伺服器上),只有前端 JS 代碼的控制權。這種場景下,應用是沒有持久化存儲的能力的。因此,按照 oAuth2.0 的規定,這種應用是拿不到 Refresh Token 的。其整個授權流程如下:4. 客戶端模式: 如果信任關係再進一步,或者調用者是一個後端的模塊,沒有用戶界面的時候,可以使用客戶端模式。鑑權伺服器直接對客戶端進行身份驗證,驗證通過後,返回 token。認證流程如下:
以上做出了筆者對於 OAuth2.0 協議的理解,關於 OAuth2.0 協議的詳細內容在此不擴展了 可訪問 騰訊開放平臺 https://wiki.connect.qq.com/ 查閱更詳細的介紹,本文在此選擇使用4中認證模式中的授權碼模式進行案例開發,這個模式也是最安全最常用的模式.
2. 開發前閱讀文檔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登陸的應用的 客戶端idredirect_uri 授權回調的地址,需要在騰訊開放平臺上填寫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登陸的應用的 客戶端idredirect_uri 授權回調的地址,需要在騰訊開放平臺上填寫client_secret:為需要qq登陸的應用的客戶端密匙4. 根據 access_token 獲取 openId (qq登陸)GET https://graph.qq.com/oauth2.0/me?access_token=CF8775A510EA68ED8576C9F675B42862
5. 再由openId和access_token向騰訊伺服器換取用戶信息
GET https://graph.qq.com/user/get_user_info? access_token=CF8775A510EA68ED8576C9F675B42862& oauth_consumer_key=12345& openid=537F314752DA3A491B4F66C04D6AD9FF
oauth_consumer_key:需要qq登陸的應用id3. 在騰訊開放平臺中創建應用了解看懂了網站接入開發的4個步驟之後那我們就進入開發準備吧!網站上的文檔說的很清晰了我們先要在開放平臺上創建應用後才能接入開發,以下是大致的應用創建過程網站地址這裡要填寫一個標準的域名地址(可以填一個假的域名)回調地址 這裡是騰訊伺服器將參數回傳到你項目中的接口填寫好之後提交,提交後應用不會立即生效可用 應用是需要審核的審核時間一周內完成!應用創建好之後登錄騰訊開放平臺點擊應用管理查看應用審核狀態如圖:在騰訊開放平臺創建好應用之後就可以正式進入寫代碼階段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,用戶表如下。用戶點擊使用 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>
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
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)
})
},
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後端 後獲取進群通道。