偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Java實(shí)現(xiàn)QQ登錄和微博登錄

開發(fā) 后端
個(gè)人網(wǎng)站最近增加了評論功能,為了方便用戶不用注冊就可以評論,對接了 QQ 和微博這 2 大常用軟件的一鍵登錄,總的來說其實(shí)都挺簡單的,可能會(huì)有一點(diǎn)小坑,但不算多,完整記錄下來方便后來人快速對接。

[[277884]]

1. 前言

個(gè)人網(wǎng)站最近增加了評論功能,為了方便用戶不用注冊就可以評論,對接了 QQ 和微博這 2 大常用軟件的一鍵登錄,總的來說其實(shí)都挺簡單的,可能會(huì)有一點(diǎn)小坑,但不算多,完整記錄下來方便后來人快速對接。

2. 后臺設(shè)計(jì)

在真正開始對接之前,我們先來聊一聊后臺的方案設(shè)計(jì)。既然是對接第三方登錄,那就免不了如何將用戶信息保存。首先需要明確一點(diǎn)的是,用戶在第三方登錄成功之后,我們能拿到的僅僅是一個(gè)代表用戶唯一身份的ID(微博是真實(shí)uid,QQ是加密的openId)以及用來識別身份的accessToken,當(dāng)然還有昵稱、頭像、性別等有限資料,對接第三方登錄的關(guān)鍵就是如何確定用戶是合法登錄,如果確定這次登錄的和上次登錄的是同一個(gè)人并且不是假冒的。

其實(shí)這個(gè)并不用我們特別操心,就以微博登錄為例,用戶登錄成功之后會(huì)回調(diào)一個(gè)code 給我們,然后我們再拿code去微博那換取accessToken,如果這個(gè)code是用戶亂填的,那這一關(guān)肯定過不了,所以,前面的擔(dān)心有點(diǎn)多余。

另外一個(gè)問題就是如何和現(xiàn)有用戶系統(tǒng)打通,有的網(wǎng)站在用戶已經(jīng)登錄成功之后還要用戶輸入手機(jī)號和驗(yàn)證碼,或者要用戶重新注冊賬號和密碼來綁定第三方賬戶,感覺這種實(shí)現(xiàn)用戶體驗(yàn)非常差,碰到這種網(wǎng)站我一般都是直接關(guān)掉,都已經(jīng)登錄了還讓用戶注冊,什么鬼!由于我做的是評論功能,我并不希望評論用戶和現(xiàn)有用戶表打通,所以就不存在這件事了,如果想打通的話,我覺得無非就是登錄成功之后默認(rèn)往老用戶表插入一條數(shù)據(jù),然后和OpenUser表關(guān)聯(lián)起來,判斷用戶是否登錄時(shí)把OpenUser的鑒權(quán)也加進(jìn)去就OK了。

本文的后臺以Java為例。

2.1. 數(shù)據(jù)庫設(shè)計(jì)

再來說說數(shù)據(jù)庫設(shè)計(jì),為了系統(tǒng)的擴(kuò)展性,我有一個(gè)專門的OpenUser表用來存放第三方登錄用戶,主要字段如下:

 

這樣設(shè)計(jì)理論上就可以無限擴(kuò)展了。

 

 

2.2. 鑒權(quán)流程

這里我只是說說我的方案,把a(bǔ)ccessToken寫入cookie肯定是不安全的,因?yàn)閍ccessToken相當(dāng)于是第三方網(wǎng)站的臨時(shí)密碼,被別人竊取了就可以隨意拿來干壞事了??梢栽谟脩舻卿洺晒χ笪覀冏约荷梢粋€(gè)token,這樣的token即使泄露了頂多就是被人拿來隨意評論,損失不大,但是如果accessToken被泄露了,以微博為例,人家可以利用這個(gè)accessToken隨意發(fā)微博、刪微博、加關(guān)注等等,很危險(xiǎn)。當(dāng)然,如果不想token泄露的話也可以通過綁定IP等方式來限制。鑒權(quán)的話就是首先判斷cookie中是否有我們自己的token,然后判斷是否合法,合法再判斷第三方授權(quán)是否已過期等等。

QQ登陸

3.1. 實(shí)名認(rèn)證

QQ登錄我們對接的是QQ互聯(lián),地址:https://connect.qq.com ,首先需要注冊成為開發(fā)者并實(shí)名認(rèn)證,需要手持身份證照片,具體就不講了。

3.2. 創(chuàng)建應(yīng)用

進(jìn)入應(yīng)用管理頁面(https://connect.qq.com/manage.html#/)創(chuàng)建應(yīng)用,根據(jù)實(shí)際需要是創(chuàng)建網(wǎng)站應(yīng)用還是移動(dòng)應(yīng)用,我這里是網(wǎng)站應(yīng)用:

 

 

 

 

第一步:

 

 

 

 

第二步:

 

 

 

 

提交完之后會(huì)自動(dòng)提交審核,基本上就是審核你的資料和備案的資料是否一致,所有資料必須和備案資料一模一樣,否則審核不會(huì)通過:

 

 

 

 

當(dāng)然,這些資料后面還是可以修改的。申請成功之后你會(huì)得到appId和appKey。

3.3. 引導(dǎo)用戶登錄

這里可以下載一些視覺素材,在頁面合適位置放一個(gè)QQ登錄按鈕,點(diǎn)擊時(shí)引導(dǎo)用戶進(jìn)入授權(quán)頁面:

 

 

 

 

代碼:

  1. function openWindow(url, width, height) 
  2.     width = width || 600; 
  3.     height = height || 400; 
  4.     var left = (window.screen.width - width) / 2; 
  5.     var top = (window.screen.height - height) / 2; 
  6.     window.open(url, "_blank""toolbar=yes, location=yes, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=no, copyhistory=yes, left="+left+", top="+top+", width="+width+", height="+height); 
  7.  
  8. function qqLogin() 
  9.     var qqAppId = '424323422'; // 上面申請得到的appid 
  10.     var qqAuthPath = 'http://www.test.com/auth'; // 前面設(shè)置的回調(diào)地址 
  11.     var state = 'fjdslfjsdlkfd'; // 防止CSRF攻擊的隨機(jī)參數(shù),必傳,登錄成功之后會(huì)回傳,最好后臺自己生成然后校驗(yàn)合法性 
  12.     openWindow(`https://graph.qq.com/oauth2.0/authorize?response_type=token&client_id=${qqAppId}&redirect_uri=${encodeURIComponent(qqAuthPath)}&state=${state}`); 

然后會(huì)打開一個(gè)授權(quán)頁面,這個(gè)頁面大家應(yīng)該都熟悉:

 

 

 

 

然后到了這里我就碰到一個(gè)問題了,官方文檔(https://wiki.connect.qq.com)寫的是登錄成功之后首先會(huì)回傳一個(gè)code,然后再拿code調(diào)接口換取accessToken,然后我試了很多次也換過2個(gè)賬號發(fā)現(xiàn)每次都是直接返回了accessToken,幫我省了一步了,不知道是什么情況,郁悶。微信搜索 Web項(xiàng)目聚集地 獲取更多實(shí)戰(zhàn)教程。

3.4. 拿到accessToken

現(xiàn)在假設(shè)我們都是直接拿到accessToken(因?yàn)槲視簳r(shí)還沒搞明白QQ為啥會(huì)直接返回,跟文檔說的不一樣),但是授權(quán)回調(diào)時(shí)accessToken會(huì)被放在 # 后面,URL地址中的hash值好像不會(huì)被傳到后臺(貌似是這樣,如有不正確歡迎評論指正),所以只能寫一個(gè)下面這樣的臨時(shí)頁面:

  1. @RequestMapping("/authqq"
  2. public void authQQ(HttpServletRequest request, HttpServletResponse response) throws Exception 
  3.     // QQ登錄有點(diǎn)特殊,參數(shù)放在#后面,后臺無法獲取#后面的參數(shù),只能用JS做中間轉(zhuǎn)換 
  4.     String html =   "<!DOCTYPE html>" + 
  5.                     "<html lang=\"zh-cn\">" + 
  6.                     "<head>" + 
  7.                     "   <title>QQ登錄重定向頁</title>" + 
  8.                     "   <meta charset=\"utf-8\"/>" + 
  9.                     "</head>" + 
  10.                     "<body>" + 
  11.                     "   <script type=\"text/javascript\">" + 
  12.                     "   location.href = location.href.replace('#', '&').replace('auth_qq', 'auth_qq_redirect');" + 
  13.                     "    
  14. </script> 
  15. " + 
  16.                     "</body>" + 
  17.                     "</html>"
  18.     response.getWriter().print(html); 

3.5. 獲取openId

根據(jù)accessToken調(diào)接口獲取用戶的openId,特別注意這個(gè)openId是相對于QQ號+appId唯一的,換句話說同一個(gè)QQ號登錄2個(gè)不同appId時(shí)獲取到的openId是不同的。順便說一句,QQ登錄的相關(guān)接口做的還真夠“隨便”的,全部都是最簡單的get請求,所以對接起來非常順利。 微信搜索 Web項(xiàng)目聚集地 獲取更多實(shí)戰(zhàn)教程。直接看代碼:

  1. // 根據(jù)accessToken換取openId 
  2. // 錯(cuò)誤示例:callback( {"error":100016,"error_description":"access token check failed"} ); 
  3. // 正確示例:callback( {"client_id":"10XXXXX49","openid":"CF2XXXXXXXX9F4C"} ); 
  4. String result = HttpsUtil.get("https://graph.qq.com/oauth2.0/me?access_token=" + accessToken); 
  5. Map<String, Object> resp = parseQQAuthResponse(result); // 這個(gè)方法就是把結(jié)果轉(zhuǎn)Map 
  6. // 歡迎關(guān)注 Web項(xiàng)目聚集地 獲取更多實(shí)戰(zhàn)教程 
  7. Integer errorCode = (Integer)resp.get("error"); 
  8. String errorMsg = (String)resp.get("error_description"); 
  9. String openId = (String)resp.get("openid"); 
  10. if(errorCode != nullreturn new ErrorResult(errorCode, "獲取QQ用戶openId失敗:"+errorMsg); 

3.6. 獲取用戶頭像昵稱等信息

  1. // 獲取用戶昵稱、頭像等信息,{ret: 0, msg: '', nickname: '', ...} ret不為0表示失敗 
  2. result = HttpsUtil.get("https://graph.qq.com/user/get_user_info?access_token="+accessToken+"&oauth_consumer_key="+appId+"&openid="+openId); 
  3. resp = JsonUtil.parseJsonToMap(result); 
  4. // 歡迎關(guān)注 Web項(xiàng)目聚集地 獲取更多實(shí)戰(zhàn)教程 
  5. Integer ret = (Integer)resp.get("ret"); 
  6. String msg = (String)resp.get("msg"); 
  7. if(ret != 0) return new ErrorResult("獲取用戶QQ信息失?。?quot;+msg); 
  8.  
  9. // 用戶昵稱可能存在4個(gè)字節(jié)的utf-8字符,MySQL默認(rèn)不支持,直接插入會(huì)報(bào)錯(cuò),所以過濾掉 
  10. String nickname = StringUtil.filterUtf8Mb4((String)resp.get("nickname")).trim(); // 這個(gè)方法可以自行百度 
  11. // figureurl_qq_2=QQ的100*100頭像,figureurl_2=QQ 100&100空間頭像,QQ頭像不一定有,空間頭像一定有 
  12. String avatar = (String)resp.get("figureurl_qq_2"); 
  13. if(StringUtil.isBlank(avatar)) avatar = (String)resp.get("figureurl_2"); 
  14. String gender = (String)resp.get("gender"); 

3.7. 注意事項(xiàng)

到了這一步基本上涉及第三方的就結(jié)束了,是不是很簡單?后面無非就是如何插入數(shù)據(jù)庫、如何保存token、寫入session等。有幾點(diǎn)注意事項(xiàng):

需要注意數(shù)據(jù)庫中是否已經(jīng)有改用戶,沒有的添加,有的修改,不要重復(fù)添加了;

QQ昵稱昵稱有各種奇奇怪怪的字符,包括emoji,MySQL默認(rèn)沒有開啟utf8mb4,直接插入會(huì)報(bào)錯(cuò),所以需要過濾掉;

  • 需要做好對各種錯(cuò)誤的兼容;
  • 接口會(huì)同時(shí)返回QQ頭像和空間頭像,QQ頭像不一定有,空間頭像一定有;
  • 回調(diào)地址必須和申請的域名一致,否則會(huì)報(bào)錯(cuò)。
  • QQ互聯(lián)有個(gè)特大的bug,有時(shí)候顯示已登錄但是點(diǎn)擊授權(quán)管理一直報(bào)錯(cuò),此時(shí)只需要退出重新登錄即可;
  • 授權(quán)之后用戶可能會(huì)在過期之前提前取消授權(quán);
  • 微信搜索 Web項(xiàng)目聚集地 獲取更多實(shí)戰(zhàn)教程。

相關(guān)文檔官網(wǎng)已經(jīng)寫得比較細(xì)了,但是比較亂:http://wiki.connect.qq.com/

對接微博登陸

4.1. 實(shí)名認(rèn)證

這個(gè)我就不具體講了,登錄 http://open.weibo.com/ 很容易找到相關(guān)入口,注冊成為開發(fā)者,實(shí)名認(rèn)證,一模一樣的。

4.2. 創(chuàng)建應(yīng)用

點(diǎn)擊鏈接 http://open.weibo.com/apps/new?sort=web 創(chuàng)建web應(yīng)用:

 

 

 

 

創(chuàng)建成果后完善相關(guān)信息,主要是下面這些:

 


 

 

我就不一一介紹了,都看得懂。微博登錄不需要網(wǎng)站一定要備案,但對網(wǎng)站本身有一定要求,不能弄一個(gè)空殼網(wǎng)站讓人家去審核,肯定審核不通過的。

有關(guān)微博的對接可以參考我好幾年前寫的一篇文章:

http://www.cnblogs.com/liuxianan/archive/2012/11/11/2765123.html

4.3. 引導(dǎo)用戶登錄

微博視覺素材(https://open.weibo.com/wiki/微博標(biāo)識下載)下載在這里,頁面合適位置放一個(gè)登錄按鈕:

  1. function weiboLogin() 
  2.     let weiboAppId = '432432'
  3.     let weiboAuthPath = 'http://www.test.com/authweibo'
  4.     openWindow(`https://api.weibo.com/oauth2/authorize?client_id=${weiboAppId}&response_type=code&redirect_uri=${encodeURIComponent(weiboAuthPath)}`); 

微博登錄有一個(gè)好處,第一次登錄需要授權(quán),后面第二次登錄時(shí)只會(huì)一閃而過自動(dòng)就登錄成功了,都不需要點(diǎn)一下,用戶體驗(yàn)非常好,看下圖:

 

 

4.4. 獲取accessToken

登錄成功會(huì)返回一個(gè)code,根據(jù)code換取accessToken:

  1. String params = "client_id=" + appId 
  2.         + "&client_secret=" + appSecret 
  3.         + "&grant_type=authorization_code" 
  4.         + "&redirect_uri=" + URLUtil.encode(authPath) 
  5.         + "&code=" + code; 
  6. // 用code換取accessToken 
  7. String result = HttpsUtil.post("https://api.weibo.com/oauth2/access_token", params); 
  8. Map<String, Object> resp = JsonUtil.toObject(result, new TypeReference<Map<String, Object>>(){}); 
  9.  
  10. Integer errorCode = (Integer)resp.get("error_code"); 
  11. String error = (String)resp.get("error"); 
  12. String errorMsg = (String)resp.get("error_description"); 
  13. if(errorCode != null && errorCode != 0) return new ErrorResult(errorCode, error + (errorMsg==null?"":errorMsg)); 
  14. String accessToken = (String)resp.get("access_token"); 
  15. String uid = (String)resp.get("uid"); // 這個(gè)uid就是微博用戶的唯一用戶ID,可以通過這個(gè)id直接訪問到用戶微博主頁 
  16. int expires = (Integer)resp.get("expires_in"); // 有效期,單位秒 

4.5. 獲取用戶頭像等信息

  1. // 用uid和accessToken換取用戶信息 
  2. String result = HttpsUtil.get("https://api.weibo.com/2/users/show.json?access_token="+accessToken+"&uid="+uid); 
  3. Map<String, Object> resp = JsonUtil.toObject(result, new TypeReference<Map<String, Object>>(){}); 
  4.  
  5. errorCode = (Integer)resp.get("error_code"); 
  6. error = (String)resp.get("error"); 
  7. errorMsg = (String)resp.get("error_description"); 
  8. if(errorCode != null && errorCode != 0) return new ErrorResult(errorCode, error + (errorMsg==null?"":errorMsg)); 
  9.  
  10. String nickname = (String)resp.get("screen_name"); 
  11. // 微博180*180高清頭像 
  12. String avatar = (String)resp.get("avatar_large"); 
  13. String gender = (String)resp.get("gender"); 
  14. gender = "m".equals(gender) ? "男" : ("f".equals(gender) ? "女" : ""); 

至此涉及第三方的東西都完了,剩下的就是用戶自己保存到數(shù)據(jù)庫、寫入token保存 session 以及鑒權(quán)接口開發(fā)了。

4.6. 注意事項(xiàng)

  • 微博接口都有頻率限制,不過一般不會(huì)超過;
  • 需做好錯(cuò)誤兼容;
  • 微博直接返回的uid,可以根據(jù)這個(gè)uid直達(dá)用戶微博主頁 https://weibo.com/u/xxxxx ,所以可以把用戶頭像鏈接到這里;
  • 其實(shí)也有現(xiàn)成的js-sdk,可以根據(jù)自己實(shí)際需要選擇是否使用;
  • 微博的接口是https,并且是post,需要注意;

 

責(zé)任編輯:龐桂玉 來源: Java團(tuán)長
相關(guān)推薦

2017-09-21 10:02:02

Java網(wǎng)頁爬蟲Httpclient

2012-02-15 17:39:36

2014-11-04 10:30:32

新浪微博可登錄任意賬戶

2021-12-06 09:44:30

鴻蒙HarmonyOS應(yīng)用

2015-08-07 15:32:19

歡迎界面仿微信仿qq空間

2012-03-16 10:45:43

Java

2023-03-26 00:00:00

2015-10-23 14:53:25

qq授權(quán)登陸

2021-12-06 16:35:33

QQ微博社交軟件

2015-04-16 10:35:08

微博微博如何實(shí)現(xiàn)

2012-05-31 13:59:43

PHP

2020-07-16 10:13:54

安全 信息安全人臉識別

2010-06-04 10:12:43

馬化騰

2018-01-29 14:01:17

htmljavascriptApp

2021-11-26 22:25:48

QQQQ音樂移動(dòng)應(yīng)用

2019-11-27 19:29:17

QQ微信移動(dòng)應(yīng)用

2021-03-05 06:39:54

指紋Web識別

2015-08-28 09:40:39

自動(dòng)登錄webapp

2016-12-22 09:11:24

Windows 10Windows 8Windows 7

2023-11-20 08:29:33

Vue微信掃碼授權(quán)登錄
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號