天天看點

OAuth2.0實戰

微信開發三大坑:

1、微信OAuth2.0授權

2、微信jssdk簽名

3、微信支付簽名

本篇先搞定微信OAuth2.0授權吧!

實際一旦了解微信的OAuth2.0,其他的也掌握了。

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

OAuth2.0實戰

簡書登陸.jpg

1) 傳統的注冊登陸方式:

如果你是一個新使用者,則點選新使用者注冊按鈕,進入由簡書提供的注冊頁面,進行使用者名密碼驗證和設定

OAuth2.0實戰

簡書注冊.jpg

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

缺點(站在使用者的角度):

  • 除非我很想使用該app,否則根本不想花這麼多時間進行注冊,太麻煩了。
  • 如果使用app很多,到處注冊,密碼要麼一樣,要麼多到你記不住
  • 每次登陸還要手動輸入使用者名以及密碼,也是很麻煩的事情

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

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

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

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

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

2) oauth2.0授權登陸:

OAuth2.0實戰

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

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

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

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

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

什麼是oatuh2.0協定:

  • OAuth2.0(開放授權)是一個開放标準。

    沒啥好解釋的,就是一個标準

  • 允許第三方網站在使用者授權的前提下通路在使用者在服務商那裡存儲的各種資訊。

    蘊含很多資訊哦!

    這句話提到了三個角色:第三方網站/使用者/服務商

    這句話是站在服務商的角度進行描述的。

    服務商:以微信為例子,那麼服務商就是微信[伺服器]或騰訊

    使用者 : 就是你,你的相關資訊(例如使用者名/密碼/性别/ 省份等等等等)都是存放在服務商的伺服器中。注意:你不是第三方(例如簡書)的使用者,而是微信的使用者(因為你是注冊在微信中,而不是簡書中)

    第三方網站 : 這裡指的就是簡書[伺服器]

  • 而這種授權無需将使用者提供使用者名和密碼提供給該第三方網站。

    這句話的意思很明顯,就是簡書伺服器是沒法拿到你在微信伺服器中的使用者名和密碼的,但是的确能夠讓你登陸簡書伺服器

  • 既然第三方(簡書)無法拿到你的使用者名和密碼,那肯定是由服務商(微信)來進行驗證,那麼第三方肯定要和服務商有一種機制來進行辨識:

    在認證過程之前,第三方(簡書)需要先向服務商(微信)申請第三方(簡書)服務的唯一辨別

    是以第三方(簡書)填寫本公司相關資訊,提供本公司賬号,域名等資訊,并且花三百塊錢給服務商(騰訊)進行稽核。服務商騰訊收到錢,并且稽核通過後,會給第三方(簡書)兩個編号:AppID和appSecret(及其重要,不能洩露)。通過這兩個編号,就能确認唯一性了。當然過程是很複雜的。

OAuth2.0實戰

appID.png

  • 第三方[伺服器]和服務商[伺服器]之間的通信:

    既然第三方(簡書)用通過服務商(微信)來驗證使用者(你)身份的合法性,那麼肯定涉及到:一旦服務商(微信)确認使用者(你)的合法身份後,如何将資訊傳遞給第三方(簡書)

    很簡單,通過第三方(簡書伺服器)提供的回調URL,服務商(微信伺服器)将相關資料以參數形式寫入到第三方(簡書伺服器)提供的回調URL,第三方(簡書伺服器)解析服務商(微信伺服器)發過來的資訊抽取出來就OK了!

    那在微信公衆号的申請中,有要求第三方(簡書)提供回調位址

OAuth2.0實戰

微信oauth2.0網頁授權回調位址設定.png

OAuth2.0實戰

不是這個頁面中的回調位址.png

oauth2.0授權流程:

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, '   '));

      });

});
           
OAuth2.0實戰

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等從微信擷取相關資訊了

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

4) 下一步計劃:

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

[開發周記2017/3/26-2017/4/2]

(http://www.jianshu.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登陸成功的圖檔:

OAuth2.0實戰

github_oauth2_授權成功後的傳回資料.png

OAuth2.0實戰

fb_oauth2授權.jpg

OAuth2.0實戰

通過fb賬号登陸local伺服器.jpg

作者:随風而行之青衫磊落險峰行

連結:http://www.jianshu.com/p/1c48ec65936b

來源:簡書

著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

繼續閱讀