微信第三方授權登入之oauth開發
背景:
首先copy下別人講解的oauth2.0驗證授權的一些背景知識:
1) 傳統的註冊登陸方式:
如果你是一個新使用者,則點選新使用者註冊按鈕,進入由簡書提供的註冊頁面,進行使用者名稱密碼驗證和設定
然後再回到簡書提供的登陸頁面,輸入剛註冊的使用者名稱和密碼進行登陸
缺點(站在使用者的角度):
-
除非我很想使用該app,否則根本不想花這麼多時間進行註冊,太麻煩了。
-
如果使用app很多,到處註冊,密碼要麼一樣,要麼多到你記不住
- 每次登陸還要手動輸入使用者名稱以及密碼,也是很麻煩的事情
優點(站在app提供者的角度):
- 對app提供者來說,新客戶註冊對其吸引投資,增加市值,加強影響力是有非常大的幫助。
那麼有什麼好的方法,能夠避免掉使用者註冊登陸的不便之處呢?答案就是: 利用各個社交app(例如微信)現有的註冊賬號進行第三方(例如簡書)應用的驗證授權登陸,這就是傳說中的oauth2.0授權登陸。
之所以使用社交軟體賬號是因為使用者實在是夠多啊!作為國人,大家基本上都有微信,qq等賬號。這樣就只要點選一下簡書登陸頁面中的社交賬號直接登陸中某個圖示就直接進入由社交app提供的授權頁面
2) oauth2.0授權登陸:
上圖顯示了簡書使用微信/qq/豆瓣/新浪微博進行oauth2.0授權登陸的介面,該介面並不是由簡書提供的,而是由對應的各個社交app提供的
上面四個介面中,微信登陸只要按確認登陸就能登陸簡書app(不要註冊,不要填寫使用者名稱+密碼,只要點選確認登陸就能登陸簡書。甚至可以通過靜默授權,連這個頁面都不需要顯示就直接進入簡書)。
其他的三個介面還是需要輸入對應社交app的使用者名稱+密碼。這是因為我只打開了微信app,qq沒開,至於豆瓣以及新浪微博,我還沒有賬號。
3) 以簡書為例子,來簡單說明oauth2.0授權登陸流程:
什麼是oatuh2.0協議:
-
OAuth2.0(開放授權)是一個開放標準。
沒啥好解釋的,就是一個標準 -
允許第三方網站在使用者授權的前提下訪問在使用者在服務商那裡儲存的各種資訊。
蘊含很多資訊哦!
這句話提到了三個角色:第三方網站/使用者/服務商
這句話是站在服務商的角度進行描述的。
服務商:以微信為例子,那麼服務商就是微信[伺服器]或騰訊
使用者 : 就是你,你的相關資訊(例如使用者名稱/密碼/性別/ 省份等等等等)都是存放在服務商的伺服器中。注意:你不是第三方(例如簡書)的使用者,而是微信的使用者(因為你是註冊在微信中,而不是簡書中)
第三方網站 : 這裡指的就是簡書[伺服器] -
而這種授權無需將使用者提供使用者名稱和密碼提供給該第三方網站。
這句話的意思很明顯,就是簡書伺服器是沒法拿到你在微信伺服器中的使用者名稱和密碼的,但是的確能夠讓你登陸簡書伺服器 - 既然第三方(簡書)無法拿到你的使用者名稱和密碼,那肯定是由服務商(微信)來進行驗證,那麼第三方肯定要和服務商有一種機制來進行辨識:
在認證過程之前,第三方(簡書)需要先向服務商(微信)申請第三方(簡書)服務的唯一標識
因此第三方(簡書)填寫本公司相關資訊,提供本公司賬號,域名等資訊,並且花三百塊錢給服務商(騰訊)進行稽核。服務商騰訊收到錢,並且稽核通過後,會給第三方(簡書)兩個編號:AppID和appSecret(及其重要,不能洩露)。通過這兩個編號,就能確認唯一性了。當然過程是很複雜的。
- 第三方[伺服器]和服務商[伺服器]之間的通訊:
既然第三方(簡書)用通過服務商(微信)來驗證使用者(你)身份的合法性,那麼肯定涉及到:一旦服務商(微信)確認使用者(你)的合法身份後,如何將資訊傳遞給第三方(簡書)
很簡單,通過第三方(簡書伺服器)提供的回撥URL,服務商(微信伺服器)將相關資料以引數形式寫入到第三方(簡書伺服器)提供的回撥URL,第三方(簡書伺服器)解析服務商(微信伺服器)發過來的資訊抽取出來就OK了!
那在微信公眾號的申請中,有要求第三方(簡書)提供回撥地址
oauth2.0授權流程:
其中:
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等從微信獲取相關資訊了
程式碼實現:
首先安裝必要庫:
npm install wechat-oauth --save
通過微信授權獲取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, ' '));
});
});
請求程式碼:
//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等從微信獲取相關資訊了.
通過上面的描述,大家可能都已經清楚第三方授權登入的意思了。
二維碼實現:
其實上面已經說的很清楚了,在進行二維碼實現登入的時候,只是將上述的請求程式碼:也就是第二塊程式碼以二維碼的方式實現而已。
html頁面中操作:
1,引入html頁面:
<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
2,html下面加入這段js物件
<script type="text/javascript">
var obj = new WxLogin({
id:"login_container", // 需要顯示的容器id
appid: "", // 公眾號appid wx*******
scope: "snsapi_login,snsapi_userinfo", // 網頁預設即可
redirect_uri: "", // 授權成功後回撥的url
state: "", // 可設定為簡單的隨機數加session用來校驗
style: "black", // 提供"black"、"white"可選。二維碼的樣式
href: "" // 外部css檔案url,需要https
});
</script>
3,需要展示二維碼的地方加入如下標籤(注意id和js物件的id要一致)
<div class="login_fast" id="login_container">
使用者掃碼點選確認後,會進入到對應的回撥函式的地址。然後在那個地方按照上訴程式碼實現,獲取token拿取資料即可。才開始我沒想到用wechat-oauth這個模組,都是自己一個簡單的實現資訊獲取。到後來,用了oauth發現,還是別人封裝的好用啊,在此謝謝樸靈那些老前輩們。下面是我隨便寫的實現,比較low雞,隨便看看。
.get('/getAcceccToken',(req,res)=>{
let code = req.query.code;
let state = req.query.state;
if(!!state) console.log('This set state is :'+state)
if(!!code) {
new Promise((resolve,reject) =>{
let secret = '947a16a2f016c9e4449196e8a';
let appId = 'wx9801d8964965481545154052';
request('https://api.weixin.qq.com/sns/oauth2/access_token?appid='+appId+'&secret='+secret+'&code='+code+'&grant_type=authorization_code',(error,res,body) =>{
if (!error && res.statusCode == 200) {
console.log(body) // Show the HTML for the baidu homepage.
resolve(body)
}else{
reject('error')
}
})
}).then(data =>{
console.log(typeof(data))
data = JSON.parse(data);
let access_token = data.access_token,
openid = data.openid;
return new Promise((resolve,reject) =>{
request('https://api.weixin.qq.com/sns/userinfo?access_token='+access_token+'&openid='+openid,(error,res,body) =>{
if (!error && res.statusCode == 200) {
console.log(body) // Show the HTML for the baidu homepage.
resolve(body)
}else{
reject('error')
}
})
})
}).then(data =>{
console.log(data)
data = JSON.parse(data)
res.json(data)
}).catch(err => res.send(err))
}
})
以上的都是我結合別人的部落格和自己的實踐總結出來的。下面把借鑑的部落格都貼出來共享吧。畢竟別的博主都寫的這麼棒。