OAuth2.0實戰1(分析簡書的微信登陸及實現)

微信開發三大坑:
1、微信OAuth2.0授權
2、微信jssdk簽名
3、微信支付簽名

本篇先搞定微信OAuth2.0授權吧!
實際一旦了解微信的OAuth2.0,其他的也掌握了。

以簡書的登陸頁面為例,來了解一下oauth2.0驗證授權的一些背景知識:

簡書登陸.jpg
  1. 傳統的注冊登陸方式:
    如果你是一個新用戶,則點擊新用戶注冊按鈕,進入由簡書提供的注冊頁面,進行用戶名密碼驗證和設置
簡書注冊.jpg

然后再回到簡書提供的登陸頁面,輸入剛注冊的用戶名和密碼進行登陸

缺點(站在用戶的角度):

  • 除非我很想使用該app,否則根本不想花這么多時間進行注冊,太麻煩了。

  • 如果使用app很多,到處注冊,密碼要么一樣,要么多到你記不住

  • 每次登陸還要手動輸入用戶名以及密碼,也是很麻煩的事情

優點(站在app提供者的角度):

  • 對app提供者來說,新客戶注冊對其吸引投資,增加市值,加強影響力是有非常大的幫助。

那么有什么好的方法,能夠避免掉用戶注冊登陸的不便之處呢?

答案就是: 利用各個社交app(例如微信)現有的注冊賬號進行第三方(例如簡書)應用的驗證授權登陸,這就是傳說中的oauth2.0授權登陸。

之所以使用社交軟件賬號是因為用戶實在是夠多啊!作為國人,大家基本上都有微信,qq等賬號。這樣就只要點擊一下簡書登陸頁面中的社交賬號直接登陸中某個圖標就直接進入由社交app提供的授權頁面

  1. oauth2.0授權登陸:
簡書通過oauth2.0授權登陸.jpg

上圖顯示了簡書使用微信/qq/豆瓣/新浪微博進行oauth2.0授權登陸的界面,該界面并不是由簡書提供的,而是由對應的各個社交app提供的

上面四個界面中,微信登陸只要按確認登陸就能登陸簡書app(不要注冊,不要填寫用戶名+密碼,只要點擊確認登陸就能登陸簡書。甚至可以通過靜默授權,連這個頁面都不需要顯示就直接進入簡書)。

其他的三個界面還是需要輸入對應社交app的用戶名+密碼。這是因為我只打開了微信app,qq沒開,至于豆瓣以及新浪微博,我還沒有賬號。

  1. 以簡書為例子,來簡單說明oauth2.0授權登陸流程:

什么是oatuh2.0協議:

  • OAuth2.0(開放授權)是一個開放標準。
    沒啥好解釋的,就是一個標準

  • 允許第三方網站用戶授權的前提下訪問在用戶服務商那里存儲的各種信息。
    蘊含很多信息哦!
    這句話提到了三個角色:第三方網站/用戶/服務商
    這句話是站在服務商的角度進行描述的。
    服務商:以微信為例子,那么服務商就是微信[服務器]或騰訊
    用戶 : 就是的相關信息(例如用戶名/密碼/性別/ 省份等等等等)都是存放在服務商的服務器中。注意:你不是第三方(例如簡書)的用戶,而是微信的用戶(因為你是注冊在微信中,而不是簡書中)
    第三方網站 : 這里指的就是簡書[服務器]

  • 而這種授權無需將用戶提供用戶名和密碼提供給該第三方網站
    這句話的意思很明顯,就是簡書服務器是沒法拿到微信服務器中的用戶名和密碼的,但是的確能夠讓登陸簡書服務器

  • 既然第三方(簡書)無法拿到你的用戶名和密碼,那肯定是由服務商(微信)來進行驗證,那么第三方肯定要和服務商有一種機制來進行辨識:
    在認證過程之前,第三方(簡書)需要先向服務商(微信)申請第三方(簡書)服務的唯一標識
    因此第三方(簡書)填寫本公司相關信息,提供本公司賬號,域名等信息,并且花三百塊錢給服務商(騰訊)進行審核。服務商騰訊收到錢,并且審核通過后,會給第三方(簡書)兩個編號:AppID和appSecret(及其重要,不能泄露)。通過這兩個編號,就能確認唯一性了。當然過程是很復雜的。

appID.png
  • 第三方[服務器]服務商[服務器]之間的通信:
    既然第三方(簡書)用通過服務商(微信)來驗證用戶(你)身份的合法性,那么肯定涉及到:一旦服務商(微信)確認用戶(你)的合法身份后,如何將信息傳遞給第三方(簡書)
    很簡單,通過第三方(簡書服務器)提供的回調URL,服務商(微信服務器)將相關數據以參數形式寫入到第三方(簡書服務器)提供的回調URL,第三方(簡書服務器)解析服務商(微信服務器)發過來的信息抽取出來就OK了!
    那在微信公眾號的申請中,有要求第三方(簡書)提供回調地址
微信oauth2.0網頁授權回調地址設定.png
不是這個頁面中的回調地址.png

oauth2.0授權流程:

oauth2.0授權流程時序圖.png

其中:
2--7步驟是通過簡書調用:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
這個API進行的,具體參數請參見文檔說明

8-9步驟是通過簡書調用:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
這個API進行的,具體參數請參見文檔說明

步驟10以后,是通過accesstoken以及openid等從微信獲取相關信息了

由于微信的開發需要審批,獨立的域名(不能使用localhost),并且要求是80端口(http)或443端口(https),這獨立域名以及這兩個端口需要工信部審批后才可使用,因此我這里目前沒有這種開發環境,但是我可以提供一段代碼,以前分享在群里面,用于進行微信oauth2.0授權,我以前可以獲取正確的結果,目前應該也可以。
只是例子而已,不要使用在生產環境:

由于使用nodejs的wechat-oauth庫進行微信oauth2.0授權操作
因此可以先npm install wechat-oauth --save下載到你的開發包中去
順便說一下,wechat-oauth是由深入淺出nodejs作者樸靈撰寫的庫

通過微信授權獲取openid和accesstoken示例代碼:

//1、引入wechat-oauth包
var OAuth = require('wechat-oauth');

//2、生成一個OAuth的實例,appId和appSecert作為構造參數
var oauthApi = new OAuth(你的appId, 你的appSecert);
//3、構造一個路由,用于獲取微信寫入到你的回調url中的code數據
//這個路由就是你注冊在微信開發中的回調url!!!!
//此時的你充當的是第三方網站角色,相當于簡書服務器
app.get('/callback', function (req, res) {  
    
    console.log('----weixin callback -----')
    var code = req.query.code;
        
    console.log("code =" + code);
    
    //通過code獲取accesstoken
    oauthApi.getAccessToken(code, function (err, result){
         //如果函數調用成功,會在result中得到access_token
        var accessToken = result.data.access_token;

        //以及openid;
        var openid = result.data.openid; 
        console.log('openid='+ openid);
         
        //然后通過openid獲取用戶信息   
        oauthApi.getUser(openid, function (err, result1) {
                
            console.log('use weixin api get user: ' + err)
                
            console.log(result)
                
            var oauth_user = result1;
             
            //打印出用戶信息
            console.log("userinfo" + JSON.stringify(oauth_user, null, '      '));
           //授權成功獲取信息后,重定向到你要去的頁面
           //這里隨便,所以直接重定向到首頁了,你可以換成其他任何頁面     
            res.redirect('/');
     });
            
            
         console.log("blf write" + JSON.stringify(result.data, null, '   '));
        
      });
        
});
demo的域名.png
 //url就是3、中定義的路由一致,用來接收微信發過來的code
//關鍵點: callbackURL必須要和3、中定義的路由一致!!!
//       且callbackURL就是你在微信中提供的回調url!!!
//就是上圖顯示的url!!!

var callbackURL = 'http://你的域名/callback';
   
   //oauth2是你定義的路由,當你點擊微信登陸這個按鈕時,就調用oauth2這個路由,向騰訊請求oauth2授權驗證
  //騰訊驗證通過,會將code寫入到3、這個回調url中
  //然后通過3、路由,獲取code, 換取accesstoken以及openid
  //再通過openid獲取userInfo,漂亮,完成整個操作

   app.get('/oauth2', function(req, res) {
  
      var url = oauthApi.getAuthorizeURL(callbackURL,'','snsapi_base');
       
      console.log(url);
 
      //重定向的回調地址,獲取code,通過code換取openid和accesstoken ,通過openid獲取用戶信息
      //所有一起如此簡單       
      res.redirect(url); 
   })

用到了wechat-oauth庫中的三個api:

oauthApi.getAuthorizeURL

相當于2--7步驟是通過調用:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
還是貼一下該函數的源碼吧,這樣就清晰了

/**
 * 獲取授權頁面的URL地址
 * @param {String} redirect 授權后要跳轉的地址
 * @param {String} state 開發者可提供的數據
 * @param {String} scope 作用范圍,值為snsapi_userinfo和snsapi_base,前者用于彈出,后者用于跳轉
 */
OAuth.prototype.getAuthorizeURL = function (redirect, state, scope) {
  var url = 'https://open.weixin.qq.com/connect/oauth2/authorize';
  var info = {
    appid: this.appid,
    redirect_uri: redirect,
    response_type: 'code',
    scope: scope || 'snsapi_base',
    state: state || ''
  };
  
  //合成授權請求url
  //然后第三方網站(你)重定向到這個url中去
  //其結果就是調用callback路由
  //于是就運行你在callback中的代碼了
  //流程銜接起來了
  return url + '?' + querystring.stringify(info) + '#wechat_redirect';
};

oauthApi.getAccessToken

相當于8-9步驟是通過調用:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

OAuth.prototype.getAccessToken = function (code, callback) {
  var url = 'https://api.weixin.qq.com/sns/oauth2/access_token';
  var info = {
    appid: this.appid,
    secret: this.appsecret,
    code: code,
    grant_type: 'authorization_code'
  };
  var args = {
    data: info,
    dataType: 'json'
  };

  //請求url,通過code換取accesstoken,openid等等
  this.request(url, args, wrapper(processToken(this, callback)));
};

oauthApi.getUser

相當于步驟10以后,是通過accesstoken以及openid等從微信獲取相關信息了

希望上面代碼對大家有幫助

  1. 下一步計劃:

由于微信的授權我這里沒有環境(其實國內的環境導致都需要獨立域名以及80/443端口問題),因此想實現一個類似騰訊的oauth2.0授權服務器。目前完成70%,還有一些問題需要解決。

[開發周記2017/3/26-2017/4/2]
(http://www.lxweimin.com/p/7417e20b74d6)

中有記錄,使用了node-oauth2-server庫開發oauth2.0服務器,但是登陸驗證的話,要使用passport,需要自己寫一個passport-strategy插件,這個有點麻煩。目前我需要向前推進,所以自己的oauth2.0授權和passport驗證放在以后實現(我覺得大概也不需要多久).

其實我的需求如下:
1、使用IBM loopback庫實現服務器
2、可以使用localhost:非80端口 進行oauth2.0授權回調,不需要獨立域名以及80/443端口
3、國內可以進行訪問,不需要那個啥(facebook/google可以使用localhost,并且非80/443端口,但是不那個啥就沒法訪問)

通過實驗,突然發現一個滿足上述所有要求的網站:
偉大的github,可以使用github開發賬戶,以localhost方式接受github發送過來的code,換取accesstoken等,進行oatuh2.0授權。
下一步我們就實戰,通過本地調用來實現github oauth2.0授權。

我們會使用loopback庫以及loopback-component-passport插件來演示一個Demo,大家會看到根本需要寫一句代碼,就能完美的進行oauth2.0授權!

IBM loopback非常好用,我會用loopback實現一個完整的服務器,與大家分享。

作為oauth2.0最后一部,我會使用node-oauth2-server以及passport實現自己的oauth2.0服務器,與大家分享實現的過程,以及node-oauth2-server(上個禮拜已經注釋好了)和passport(曾經讀過源碼,但是是去年,可能需要回憶一下,哈哈)的源碼分析

使用loopback-component-passport插件實現github和facebook登陸成功的圖片:

github_oauth2_授權成功后的返回數據.png
fb_oauth2授權.jpg
通過fb賬號登陸local服務器.jpg

下一篇我們使用vue2.0來制作一個登陸頁面,并且了解服務端loopback的基礎知識

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容