OAuth2(open Auth)開放授權協議
授權碼模式流程:
1、瀏覽器(客戶端)點擊一個比如使用微信登陸按鈕
2、會跳到認證服務器頁面,讓用戶選擇是否授權
3、如果用戶點擊授權,那么會跳轉到開始在鏈接上填寫的回調地址 (redirect_uri),同時會產生一個授權碼code
4、客戶端又拿這個code去認證服務器請求access_token
5、有了access_token就可以去調用授權的接口,access_token有效期比較短,當access_token過期后可以refresh_token刷新access_token
微信登陸流程:
為了便於調試,可以在微信開發平台的回調上寫本地服務比如egg啟動的地址localhost:7001,只要和本地設置的回調地址同域名就可以生成二維碼
1、引用http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js
2、 實例化以下對象可以生成一個二維碼
var obj = new WxLogin({
self_redirect:false, //是在iframe里跳轉還是頂層窗口跳轉
id:"login_container", //DOM容器放置二維碼的區域
appid: "", //在應用開發平台申請
scope: "snsapi_login", //如果是網頁應用填寫這個
redirect_uri: "localhost:7001/reqAccessToken",//回調地址
state: "xxx",//附帶傳遞的數據
style: "", //二維碼行內樣式
href: "" //外鏈樣式
});
3、掃描這個二維碼,會彈出授權頁,點擊授權會重定向到剛才的回調地址redirect_uri,並會自動附上code值,如果開始填了state值,這個時候也會返回剛才的state,可以用這個state的自定義值進行區分做登陸還是綁定
redirect_uri?code=CODE&state=STATE //點擊授權的返回
redirect_uri?state=STATE //不授權的返回
4、然后在比如nodejs服務路由里攔截剛才的redirect_uri地址,然后獲取這個code值,去調用獲取access_token的接口
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
//appid和secret //開放平台提供的值,填上即可
//CODE 即上一步返回的code值
5、這個獲取access_token的接口返回的數據
{
"access_token":"ACCESS_TOKEN", //調用進一步接口令牌
"expires_in":7200, //這個接口的過期時間
"refresh_token":"REFRESH_TOKEN",//刷新上面令牌的參數
"openid":"OPENID", //用戶唯一標識
"scope":"SCOPE"
}
6、用openid和access_token獲取用戶基本信息
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
//上一步返回的openid和access_token
{
"openid":"OPENID",
"nickname":"NICKNAME",
"sex":1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege":[
"PRIVILEGE1",
"PRIVILEGE2"
],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" //用這個unionid進行綁定其他信息
}
7、拿unionid和用戶填寫的其他信息進行關聯綁定,比如手機號,當用戶下次綁定的時候,發現數據庫里有了該手機號,則直接給用戶跳轉到掃碼界面進行掃碼登陸,如果當用戶下次是直接掃碼登陸,但是數據庫里沒有這個unionid,則給用戶跳轉到綁定界面讓用戶進行綁定
調試或多環境共用一個開發平台回調設置:
如果微信開發平台只注冊了一個網站應用,只能填寫一個回調地址,為了不影響本地開發調試,可以在服務端做一個轉發:
比如回調地址是111.111.111.111:7001則給開發環境和生產環境加一個標識,當回調請求111.111.111.111:7001/env/dev/reqAccessToken 則重定向到 localhost:7001/reqAccessToken,如果111.111.111.111:7001/production/reqAccessToken則重定向到111.111.111.111:7001/reqAccessToken即可,本地生成二維碼的redirect_uri就寫111.111.111.111:7001/env/${env}即可,然后服務端路由攔截/env/:env,根據env做重定向判斷。
//生成二維碼的實例化對象redirect_uri填寫
//跟微信開發平台填寫的回調地址同域名
var redirectPrefix = "https://www.xxx.com";
var CURENV = '<%=env%>';
new WxLogin({
self_redirect: false,
id: "J_wechatCodeBind",
appid: "xxx",
scope: "snsapi_login",
redirect_uri: encodeURI(`${redirectPrefix}/env/${CURENV}`),
state:"",
style: "white",
href: ""
});
//路由攔截上面的回調GET請求
async redirectUrl() {
const ctx = this.ctx;
const curEnv = ctx.params.curEnv;
const code = ctx.query.code;
const state = ctx.query.state;
if (curEnv == 'dev') {
ctx.redirect(`http://localhost:7001/xxx/xxx/requestAccessToken?code=${code}&state=${state}`);
} else if (curEnv == 'test') {
ctx.redirect(`http://192.168.0.xxx:7006/xxx/xxx/requestAccessToken?code=${code}&state=${state}`);
} else {
ctx.redirect(`https://www.xxx.com/xxx/xxx/requestAccessToken?code=${code}&state=${state}`);
}
}
