目前OAuth 2.0 認證有五種方式,見官方文檔: http://www.rfcreader.com/#rfc6749
授權碼模式(Authorization Code Grant)
流程圖

說明:
1,認證伺服器是一個業務無關的系統;
2,code就是授權碼,隻能使用一次;
3,token 在有效期内可以無限次使用
場景化講解-下單
場景:A 公司旗下有很多 web 産品,同時還有一個應用商店(類似京東)負責售賣這些軟體産品,下面以使用者進入應用商店購買産品的流程着手。
- 應用商店通過浏覽器嘗試擷取下單頁;
- 應用商店背景鑒權,發現沒有登入(應用商店背景實際會調用認證伺服器,比如校驗 access tokensh是否有效);
- 跳轉到登入頁面;(對應上圖(A))
- 使用者通過浏覽器輸入使用者名,密碼等方式進行授權(此時會調用認證伺服器接口);(對應上圖(B))
- 認證伺服器傳回臨時 code 給浏覽器;(對應上圖(C))
- 應用商店拿臨時 code 去調用認證伺服器接口,換取 access token;(對應上圖(D))
- 認證伺服器傳回 access token給應用商店;(對應上圖(E))
- 應用商店把 access token 緩存下來。
- 後續應用商店調用業務系統(比如下單接口,訂單查詢接口)接口均帶上 access token;
場景化講解-微信公衆号授權
現在很多微商系統接入了微信公衆号,通過微信公衆号售賣産品,那麼它們是如何擷取使用者資訊的呢?
我們在關注某個商店性質的微信公衆号時,經常會彈出如下對話框,要求我們授權

圖2-1
使用者點選上述界面中的"允許",對應的操作是“"授權碼模式"的(B)-- User authenticates:

具體流程如下:
- 某微信公衆号B 通路使用者資訊,用于下單支付(實際需要使用者的 openid);
- 見圖2-1,微信彈框,要求使用者授權;
- 使用者點選"允許"授權,某微信公衆号B才能擷取到臨時 code;
- 某微信公衆号B拿臨時 code調用微信鑒權接口擷取 access token 或 openid;
執行個體3-對接釘釘通訊錄實作登入
免登流程
第一步:通過使用者授權擷取code
授權連結:
https://h5.dingtalk.com/liveeasylogin/index.html#/index?appid=dingoae2vmockd44q2&response_type=code&scope=snsapi_auth&state=STATE&redirect_uri=http%3A%2F%2Flocalhost%3A7001%2Fapi%2Ftest%2FtestCode.json第二步:使用者授權
授權成功擷取code
{"content":"code=4d9954574c32afafd9xxx3c34b414aa&state=STATE","errorLevel":0,"success":true}

code 值為:4d9954574c32afafd9xxx3c34b414aa
授權測試位址
dingtalk://dingtalkclient/page/link?url=https%3A%2F%2Fh5.dingtalk.com%2Fliveeasylogin%2Findex.html%23%2Findex%3Fappid%3Ddingoaemockdlfr66612%26response_type%3Dcode%26scope%3Dsnsapi_auth%26state%3DSTATE%26redirect_uri%3Dhttp%253A%252F%252Floca77host%253A7001%252Fapi%252Ftest%252FtestCode.json%3fddtab%3dtrue
code有什麼用?
- 可以擷取使用者資訊;
- 可以擷取access_token
擷取使用者資訊
//擷取使用者資訊
DefaultDingTalkClient client = new DefaultDingTalkClient(DingTalkConstants.URL_GET_USER_INFO_BY_CODE);
OapiSnsGetuserinfoBycodeRequest request = new OapiSnsGetuserinfoBycodeRequest();
request.setTmpAuthCode(requestAuthCode);
request.setHttpMethod(HttpMethod.POST.toString());
OapiSnsGetuserinfoBycodeResponse response;
try {
response = client.execute(request, dingTalkProperties.getAppid(), dingTalkProperties.getAppsecret());
} catch (ApiException e) {
logger.error("accessToken:{0}, url:{1}", "", DingTalkConstants.URL_GET_USER_INFO_BY_CODE, e);
return null;
}
LoginedUser loginedUser = null;
if (response.isSuccess() && null != response.getUserInfo()) {
OapiSnsGetuserinfoBycodeResponse.UserInfo userInfo = response.getUserInfo();
擷取access_token
略