授權服務如何生成通路令牌?
通路令牌過期了而使用者又不在場的情況下,又如何重新生成通路令牌?
授權服務的工作過程
在 xx讓我去公衆号開放平台給它授權資料時,你是否好奇?開放平台怎麼知道 xx 是誰?他合法備案了嗎?萬一是個病毒軟體咋辦?
是以,授權的前提是xx要去開放平台備案,即注冊。之後,開放平台就會給xx軟體app_id和app_secret等,友善後面授權時的各種校驗。
注冊時,三方軟體也會請求受保護資源的可通路範圍。比如,xx能否擷取我的公衆号半年前的文章,能否擷取每個文章的所有資訊(比如标題、封面、标簽)等。即scope。
注冊後,xx過來讓平台把我的文章資料都給xx,平台核實後确認xx合法。
咱們上節課講過,在授權碼許可類型中,授權服務的工作,可以劃分為兩大部分,一個是頒發授權碼code,一個是頒發通路令牌access_token。

頒發授權碼code流程
過程 1:頒發授權碼code
授權服務負責準備工作和生成授權碼code。
準備工作
包括驗證基本資訊、權限範圍(第一次)和生成授權請求頁面。
驗證基本資訊
Web 頒發code的整個請求過程,都是通過浏覽器由前端通信完成,意味着所有資訊都可能被僞造,比如回調位址,将其僞裝成釣魚頁面,授權服務需要對回調位址做基本的校驗。
授權服務必須對三方軟體的存在性判斷。
if(!appMap.get("redirect_uri").equals(redirectUri)){
//回調位址不存在
}
在授權服務的程式中,這兩步驗證通過後,就會生成或者響應一個頁面(授權伺服器上的頁面),提示小明進行授權。
第二步,驗證權限範圍(第一次)
授權就會涉及範圍。比如使用微信登入三方軟體時,微信提示我們,第三方軟體可獲得你的昵稱、頭像、性别、地理位置等。如你不想讓三方軟體擷取你的某個資訊,可不選擇該項。
即需要對xx傳過來的scope參數,與小兔注冊時申請的權限範圍對比。
此刻是第一次權限校驗。
String scope = request.getParameter("scope");
if(!checkScope(scope)){
//超出注冊的權限範圍
}
第三步,生成授權請求頁面
即授權服務上的頁面,頁面上顯示注冊時申請的權限,我可以選擇縮小這個權限範圍。
至此,頒發授權碼code準備工作完成。當使用者點選授權按鈕“approve”後,才會生成授權碼code值和通路令牌
acces_token
。
注意隻有使用者登入了才可對三方軟體授權,授權服務才能夠獲得使用者資訊并最終生成code 和 app_id(第三方軟體的應用辨別) + user(資源擁有者辨別)之間的對應關系。
我掃碼同意後,生成授權碼code的流程就開始了,主要包括驗證權限範圍(第二次)、處理授權請求生成授權碼code和重定向至第三方軟體這三大步。
第四步,驗證權限範圍(第二次)
步驟二生成授權頁面前授權服務進行的第一次校驗,是對比xx請求的權限範圍和注冊時的權限。
為什麼又要校驗一次
因為這相當于一次使用者的輸入權限。我選擇了權限範圍給授權服務,對權限的校驗,凡輸入性資料都會涉及合法性檢查。
String[] rscope =request.getParameterValues("rscope");
if(!checkScope(rscope)){
//超出注冊的權限範圍
}
第五步 處理授權請求,生成授權碼code
我同意授權後,授權服務會校驗響應類型
response_type
的值。response_type有code和token兩種類型的值。
用授權碼流程舉例,是以代碼要驗證response_type的值是否為code。
String responseType = request.getParameter("response_type");
if("code".equals(responseType)){
...
}
授權服務中,需要将生成的授權碼code值與app_id、user進行關系映射。即一個授權碼code,表示某使用者給某三方軟體授權。同時要将code和這種映射關系儲存,以便在生成通路令牌access_token時使用。
// 模拟登入使用者為USERTEST
String code = generateCode(appId,"USERTEST");
private String generateCode(String appId,String user) {
...
String code = strb.toString();
codeMap.put(code,appId+"|"+user+"|"+System.currentTimeMillis());
return code;
}
生成授權碼code後,也按照上面所述綁定了響應的映射關系。還需要為code設定有效期。
OAuth 2.0規範建議授權碼code值有效期為10分鐘,并且一個授權碼code隻能被使用一次。生産環境code有效期一般不超過5min。
授權服務還要将生成的授權碼code跟已授權的權限範圍rscope進行綁定并存儲,以便後續頒發通路令牌時,能夠通過code值取出授權範圍并與通路令牌綁定。因三方軟體最終是通過通路令牌來請求受保護資源。
Map<String,String[]> codeScopeMap = new HashMap<String, String[]>();
codeScopeMap.put(code,rscope);//授權範圍與授權碼做綁定
第六步,重定向至三方軟體
生成授權碼code後,授權服務需要将該code值告知第三方軟體。
頒發授權碼code是前端通信完成,是以這裡采用重定向。即第二次重定向
Map<String, String> params = new HashMap<String, String>();
params.put("code",code);
String toAppUrl = URLParamsUtil.appendParams(redirectUri,params);//構造第三方軟體的回調位址,并重定向到該位址
response.sendRedirect(toAppUrl);//授權碼流程的“第二次”重定向
至此,頒發授權碼code的流程全部完成。xx擷取到授權碼code值後,就可請求通路令牌access_token的值,即過程二。