梳理微信小程序登錄時(shí)序圖:授權(quán)與 Oauth2.0

目錄:
1. 做微信小程序遇到授權(quán)問題
2. 沒接觸過授權(quán),先理解授權(quán)是什么意思
3. 具體開發(fā)如何實(shí)現(xiàn)授權(quán)
  3.1 使用賬號(hào)密碼進(jìn)行傳統(tǒng)授權(quán)
  3.2 傳統(tǒng)授權(quán)顯得很蠢,Oauth 授權(quán)方式出現(xiàn)
4. 回過頭分析小程序?yàn)槭裁慈绱嗽O(shè)計(jì)授權(quán)
5. 參考文章

一详拙、遇到授權(quán)

最近開發(fā)微信小程序删性,做登錄功能時(shí)遇到下圖。

微信小程序登錄時(shí)序圖

看太懂钳吟,有幾處疑惑地方:

  • 同事告訴我這是認(rèn)證和授權(quán),之前沒接觸過,不了解是要解決什么問題瓮钥;
  • 為什么要有認(rèn)證和授權(quán),要解決什么問題烹吵;
  • appid骏庸、appsecret、openid年叮、session_key 這些單詞都是什么意思具被。

下面就是尋找答案的過程。

二只损、沒接觸過授權(quán)一姿,先理解授權(quán)是什么意思

豪車模型

如果你開車去酒店赴宴,你經(jīng)常會(huì)苦于找不到停車位而耽誤很多時(shí)間跃惫。是否有好辦法可以避免這個(gè)問題呢叮叹?有的,聽說有一些豪車的車主就不擔(dān)心這個(gè)問題爆存。豪車一般配備兩種鑰匙:主鑰匙和泊車鑰匙蛉顽。當(dāng)你到酒店后,只需要將泊車鑰匙交給服務(wù)生先较,停車的事情就由服務(wù)生去處理携冤。與主鑰匙相比,這種泊車鑰匙的使用功能是受限制的:它只能啟動(dòng)發(fā)動(dòng)機(jī)并讓車行駛一段有限的距離闲勺,可以鎖車曾棕,但無法打開后備箱,無法使用車內(nèi)其他設(shè)備菜循。這里就體現(xiàn)了一種簡單的“開放授權(quán)”思想:通過一把泊車鑰匙翘地,車主便能將汽車的部分使用功能(如啟動(dòng)發(fā)動(dòng)機(jī)、行駛一段有限的距離)授權(quán)給服務(wù)生。

鄰居模型

你和你的家人在外面游玩衙耕,突然陰雨蒙蒙昧穿,眼看就要下雨了,你想起家中的被子還在外面曬著橙喘。你給你的鄰居打電話时鸵,告訴他在你家門口地毯下面有一把鑰匙,希望他將被子收到房間中渴杆。通過告知他鑰匙的位置寥枝,就是你授權(quán)你的鄰居進(jìn)入你家的權(quán)限,雖然你只是希望他拿到被子送到客廳就出來鎖門磁奖,但是你給了他所有的權(quán)限囊拜,他不僅可以進(jìn)入客廳,還可以進(jìn)入你們的臥室比搭、廚房等冠跷,這不是你想看到的。

在上面兩個(gè)模型中身诺。豪車的主鑰匙賦予泊車鑰匙部分權(quán)限蜜托,而你賦予你的鄰居所有的權(quán)限。比較之下霉赡,我們更希望使用豪車模型賦予部分權(quán)限橄务,而不是鄰居模型,萬一他偷偷配了把鑰匙呢穴亏?這種授權(quán)存在不安全性蜂挪,在網(wǎng)絡(luò)開發(fā)中也是如此。

三嗓化、具體開發(fā)如何實(shí)現(xiàn)授權(quán)

使用 QQ 號(hào)登錄簡書

登錄簡書時(shí)可以選擇社交賬號(hào)登錄棠涮,這里以 QQ 為例。這里涉及三方:當(dāng)前要登錄簡書的用戶刺覆,以下簡稱 用戶严肪,其它兩方是:簡書QQ 服務(wù)器谦屑。因?yàn)?用戶
之前注冊(cè)過 QQ驳糯,簡書 請(qǐng)求 QQ 服務(wù)器 授權(quán)用戶的 QQ 基本信息,這樣用戶就不用在簡書上再進(jìn)行注冊(cè)了伦仍。

下面來探討下 QQ 服務(wù)器 如何授權(quán) 簡書 當(dāng)前 用戶 的 QQ 基本信息结窘。

3.1 使用賬號(hào)密碼進(jìn)行傳統(tǒng)授權(quán)

這種方法比較簡單,用戶 告訴 簡書 它的 QQ 賬號(hào)密碼充蓝,簡書拿著賬號(hào)密碼去請(qǐng)求 QQ 服務(wù)器獲取用戶基本信息。

傳統(tǒng)授權(quán)方式

優(yōu)點(diǎn):操作簡單。

缺點(diǎn):用戶將 qq 賬號(hào)密碼給了簡書谓苟,簡書獲得了該用戶在 QQ 上的所有特權(quán)官脓,不僅可以查看基本信息,還可以查看 QQ 空間涝焙,查看 QQ 郵箱等卑笨,而用戶的本意是只讓簡書獲取 QQ 基本信息這一項(xiàng)特權(quán)。

正是傳統(tǒng)授權(quán)方式存在缺陷仑撞,Oauth 2.0 授權(quán)才會(huì)出現(xiàn):只授權(quán)指定權(quán)限赤兴。

3.2 傳統(tǒng)授權(quán)顯得很蠢,Oauth2.0 授權(quán)方式出世

下面是在 小胡子哥的個(gè)人博客 里看到的隧哮,將整個(gè)授權(quán)過程講解的生動(dòng)形象桶良,我就不做二次加工,直接截取部分內(nèi)容如下沮翔。

以用戶使用 github 登錄網(wǎng)站留言為例陨帆,簡述 OAuth 2.0 的運(yùn)作流程。

假如我有一個(gè)網(wǎng)站采蚀,你是我網(wǎng)站上的訪客疲牵,看了文章想留言表示「朕已閱」,留言時(shí)發(fā)現(xiàn)有這個(gè)網(wǎng)站的帳號(hào)才能夠留言榆鼠,此時(shí)給了你兩個(gè)選擇:一個(gè)是在我的網(wǎng)站上注冊(cè)擁有一個(gè)新賬戶纲爸,然后用注冊(cè)的用戶名來留言;一個(gè)是使用 github 帳號(hào)登錄妆够,使用你的 github 用戶名來留言识啦。前者你覺得過于繁瑣,于是慣性地點(diǎn)擊了 github 登錄按鈕责静,此時(shí) OAuth 認(rèn)證流程就開始了袁滥。

需要明確的是,即使用戶剛登錄過 github灾螃,我的網(wǎng)站也不可能向 github 發(fā)一個(gè)什么請(qǐng)求便能夠拿到訪客信息题翻,這顯然是不安全的。就算用戶允許你獲取他在 github 上的信息腰鬼,github 為了保障用戶信息安全嵌赠,也不會(huì)讓你隨意獲取。所以操作之前熄赡,我的網(wǎng)站與 github 之間需要要有一個(gè)協(xié)商姜挺。

  1. 網(wǎng)站和 Github 之間的協(xié)商
    Github 會(huì)對(duì)用戶的權(quán)限做分類,比如讀取倉庫信息的權(quán)限彼硫、寫入倉庫的權(quán)限炊豪、讀取用戶信息的權(quán)限凌箕、修改用戶信息的權(quán)限等等。如果我想獲取用戶的信息词渤,Github 會(huì)要求我牵舱,先在它的平臺(tái)上注冊(cè)一個(gè)應(yīng)用,在申請(qǐng)的時(shí)候標(biāo)明需要獲取用戶信息的哪些權(quán)限缺虐,用多少就申請(qǐng)多少芜壁,并且在申請(qǐng)的時(shí)候填寫你的網(wǎng)站域名,Github 只允許在這個(gè)域名中獲取用戶信息高氮。

此時(shí)我的網(wǎng)站已經(jīng)和 Github 之間達(dá)成了共識(shí)慧妄,Github 也給我發(fā)了兩張門票,一張門票叫做 Client Id剪芍,另一張門票叫做 Client Secret塞淹。

  1. 用戶和 Github 之間的協(xié)商
    用戶進(jìn)入我的網(wǎng)站,點(diǎn)擊 github 登錄按鈕的時(shí)候紊浩,我的網(wǎng)站會(huì)把上面拿到的 Client Id 交給用戶窖铡,讓他進(jìn)入到 Github 的授權(quán)頁面,Github 看到了用戶手中的門票坊谁,就知道這是我的網(wǎng)站讓他過來的费彼,于是它就把我的網(wǎng)站想要獲取的權(quán)限擺出來,并詢問用戶是否允許我獲取這些權(quán)限口芍。
// 用戶登錄 github箍铲,協(xié)商
GET //github.com/login/oauth/authorize
// 協(xié)商憑證
params = {
  client_id: "xxxx",
  redirect_uri: "http://my-website.com"
}

如果用戶覺得我的網(wǎng)站要的權(quán)限太多,或者壓根就不想我知道他這些信息鬓椭,選擇了拒絕的話颠猴,整個(gè) OAuth 2.0 的認(rèn)證就結(jié)束了,認(rèn)證也以失敗告終小染。如果用戶覺得 OK翘瓮,在授權(quán)頁面點(diǎn)擊了確認(rèn)授權(quán)后,頁面會(huì)跳轉(zhuǎn)到我預(yù)先設(shè)定的 redirect_uri 并附帶一個(gè)蓋了章的門票 code裤翩。

// 協(xié)商成功后帶著蓋了章的 code
Location: http://my-website.com?code=xxx

這個(gè)時(shí)候资盅,用戶和 Github 之間的協(xié)商就已經(jīng)完成,Github 也會(huì)在自己的系統(tǒng)中記錄這次協(xié)商踊赠,表示該用戶已經(jīng)允許在我的網(wǎng)站訪問上直接操作和使用他的部分資源呵扛。

  1. 告訴 Github 我的網(wǎng)站要來拜訪了
    第二步中,我們已經(jīng)拿到了蓋過章的門票 code筐带,但這個(gè) code 只能表明今穿,用戶允許我的網(wǎng)站從 github 上獲取該用戶的數(shù)據(jù),如果我直接拿這個(gè) code 去 github 訪問數(shù)據(jù)一定會(huì)被拒絕伦籍,因?yàn)槿魏稳硕伎梢猿钟?code蓝晒,github 并不知道 code 持有方就是我本人腮出。
    還記得之前申請(qǐng)應(yīng)用的時(shí)候 github 給我的兩張門票么,Client Id 在上一步中已經(jīng)用過了拔创,接下來輪到另一張門票 Client Secret利诺。
// 網(wǎng)站和 github 之間的協(xié)商
POST //github.com/login/oauth/access_token
// 協(xié)商憑證包括 github 給用戶蓋的章和 github 發(fā)給我的門票
params = {
  code: "xxx",
  client_id: "xxx",
  client_secret: "xxx",
  redirect_uri: "http://my-website.com"
}

拿著用戶蓋過章的 code 和能夠標(biāo)識(shí)個(gè)人身份的 client_id富蓄、client_secret 去拜訪 github剩燥,拿到最后的綠卡 access_token。

// 拿到最后的綠卡
response = {
  access_token: "e72e16c7e42f292c6912e7710c838347ae178b4a"
  scope: "user,gist"
  token_type: "bearer",
  refresh_token: "xxxx"
}
  1. 用戶開始使用 github 帳號(hào)在我的頁面上留言
// 訪問用戶數(shù)據(jù)
GET //api.github.com/user?access_token=e72e16c7e42f292c6912e7710c838347ae178b4a

上一步 github 已經(jīng)把最后的綠卡 access_token 給我了立倍,通過 github 提供的 API 加綠卡就能夠訪問用戶的信息了灭红,能獲取用戶的哪些權(quán)限在 response 中也給了明確的說明,scope 為 user 和 gist口注,也就是只能獲取 user 組和 gist 組兩個(gè)小組的權(quán)限变擒,user 組中就包含了用戶的名字和郵箱等信息了。

// 告訴我用戶的名字和郵箱
response = {
  username: "barretlee",
  email: "barret.china@gmail.com"
}

整個(gè) OAuth2 流程在這里也基本完成了寝志。

四娇斑、回過頭分析小程序?yàn)槭裁慈绱嗽O(shè)計(jì)授權(quán)

微信小程序登錄時(shí)序圖

明確一點(diǎn):小程序和微信是兩個(gè)程序,只不過小程序的入口在微信內(nèi)材部。所以微信的接口一般小程序是不能直接調(diào)用的毫缆,得先授權(quán)。

微信小程序登錄時(shí)序圖真正的目的不是小程序自身去請(qǐng)求授權(quán)乐导,而是通過小程序去獲取授權(quán) token苦丁,然后給第三方服務(wù)器用,第三方服務(wù)器會(huì)拿這個(gè) token 去調(diào)用微信服務(wù)器授權(quán)的相關(guān)接口物臂。

1. 注冊(cè)微信公眾賬號(hào)

開發(fā)微信小程序第一步要在 微信公眾平臺(tái) 上注冊(cè)一個(gè)賬號(hào)旺拉,注冊(cè)完成后在 設(shè)置 > 開發(fā)設(shè)置 里可以看到 AppID 和 AppSecret,這相當(dāng)于上面提到的 Client Id 和 Client Secret棵磷。

2. 明確對(duì)應(yīng)關(guān)系

用戶 第三方應(yīng)用 授權(quán)服務(wù)器 備注
用戶 小胡子的網(wǎng)站 github 小胡子網(wǎng)站獲取 github 授權(quán)用戶基本信息
用戶 簡書 QQ 服務(wù)器 簡書獲取 QQ 服務(wù)器授權(quán)基本信息
微信登錄用戶 小程序 微信服務(wù)器 小程序獲得微信服務(wù)器授權(quán)可以調(diào)用一些微信接口蛾狗,如獲取微信登錄用戶的基本信息、調(diào)用微信支付接口

3. wx.login 接口獲取 code

wx.login({
    success: function(res) {
        if (res.code) {
          //發(fā)起網(wǎng)絡(luò)請(qǐng)求
          wx.request({
            url: 'https://test.com/onLogin',
            data: {
              code: res.code
            }
          })
        } else {
          console.log('獲取用戶登錄態(tài)失斠敲健沉桌!' + res.errMsg)
        }
      }
});

微信登錄用戶微信 中打開 小程序小程序 中運(yùn)行了 wx.login 接口规丽,此時(shí) 小程序 拿著 appid 去請(qǐng)求 微信服務(wù)器小程序 授權(quán)蒲牧,讓它可以調(diào)用一些微信接口,比如獲取微信登錄用戶的基本信息赌莺。因?yàn)槭?微信登錄用戶 進(jìn)行操作的冰抢,所以微信那端默認(rèn)是同意授權(quán)的。(appid 哪里來艘狭?在新建小程序項(xiàng)目時(shí)輸入挎扰,每個(gè) appid 和小程序都是一一對(duì)應(yīng)的)

新建小程序項(xiàng)目

4. 拿著 code 去獲取令牌

上面也提到翠订,這個(gè) code 可能會(huì)泄露,所以需要 code + appid + appsecret 去再次拜訪微信服務(wù)器獲取令牌 session_key 和用戶標(biāo)識(shí) openid遵倦。

這里有個(gè)疑問尽超?為什么獲取 code 在小程序上做,而獲取 session_key 在第三方服務(wù)器上操作梧躺?這是因?yàn)楂@取 code 需要使用 appid 去跳轉(zhuǎn)微信服務(wù)器授權(quán)頁面似谁,再使用當(dāng)前 微信登錄用戶 默認(rèn)同意此次授權(quán),如果坐在第三方服務(wù)器上掠哥,appid 我們是知道的巩踏,但是當(dāng)前 微信登錄用戶 是不知道,只要手機(jī)上的微信知道续搀。

那為什么請(qǐng)求 session_key 在第三方服務(wù)器上操作塞琼?這是因?yàn)榍懊嬉舱f過 code 只能表明微信服務(wù)器統(tǒng)一此次授權(quán),但是 code 可能會(huì)泄露禁舷,還需要第二張門票 appsecret 告訴微信服務(wù)器 “就是我彪杉,不是別人” 來請(qǐng)求獲取 session_key 的∏A可見 appsecret 對(duì)于安全的重要性派近,放在第三方服務(wù)器方便管理。

關(guān)于 openid 和 session_key 說明霜大?session_key 就是返回的綠卡构哺,此后每次訪問微信服務(wù)器資源都要帶上它,這樣微信服務(wù)器才知道此次請(qǐng)求是有授權(quán)的战坤,我可以把資源給你曙强。openid 是同意授權(quán)的那個(gè)人,這里是 微信登錄用戶 的標(biāo)識(shí) ID途茫。也就是為什么 code 要在小程序中獲取中我們不知道的那個(gè) 微信登錄用戶 ID碟嘴。

到此,上圖中涉及 Oauth2.0 的部分已經(jīng)結(jié)束囊卜,下面的那些都是普通的 session 維持會(huì)話機(jī)制娜扇,這里就不再贅述。

五栅组、參考文章

  1. 幫你深入理解OAuth2.0協(xié)議
  2. Oauth2.0(一):為什么需要 Oauth2.0 協(xié)議雀瓢?
  3. 簡述 OAuth 2.0 的運(yùn)作流程

六、最后

由于作者文筆有限玉掸,文章如有遺漏或表達(dá)有誤刃麸,請(qǐng)不吝賜教。如果仍對(duì)微信授權(quán)或 Oauth2.0 有疑問的司浪,歡迎留言討論泊业。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末把沼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吁伺,更是在濱河造成了極大的恐慌饮睬,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篮奄,死亡現(xiàn)場離奇詭異捆愁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)宦搬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門牙瓢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人间校,你說我怎么就攤上這事∫晨叮” “怎么了憔足?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酒繁。 經(jīng)常有香客問我滓彰,道長,這世上最難降的妖魔是什么州袒? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任揭绑,我火速辦了婚禮,結(jié)果婚禮上郎哭,老公的妹妹穿的比我還像新娘他匪。我一直安慰自己,他們只是感情好夸研,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布邦蜜。 她就那樣靜靜地躺著,像睡著了一般亥至。 火紅的嫁衣襯著肌膚如雪悼沈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天姐扮,我揣著相機(jī)與錄音絮供,去河邊找鬼。 笑死茶敏,一個(gè)胖子當(dāng)著我的面吹牛壤靶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播睡榆,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼萍肆,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼袍榆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起塘揣,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤包雀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后亲铡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體才写,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年奖蔓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赞草。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吆鹤,死狀恐怖厨疙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疑务,我是刑警寧澤沾凄,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站知允,受9級(jí)特大地震影響撒蟀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜温鸽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一保屯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涤垫,春花似錦姑尺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吱雏,卻和暖如春敦姻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背歧杏。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國打工镰惦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人犬绒。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓旺入,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子茵瘾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容