天天看點

授權服務是如何頒發授權碼和通路令牌的?(上)授權服務的工作過程頒發授權碼code流程

授權服務如何生成通路令牌?

通路令牌過期了而使用者又不在場的情況下,又如何重新生成通路令牌?

授權服務的工作過程

在 xx讓我去公衆号開放平台給它授權資料時,你是否好奇?開放平台怎麼知道 xx 是誰?他合法備案了嗎?萬一是個病毒軟體咋辦?

是以,授權的前提是xx要去開放平台備案,即注冊。之後,開放平台就會給xx軟體app_id和app_secret等,友善後面授權時的各種校驗。

注冊時,三方軟體也會請求受保護資源的可通路範圍。比如,xx能否擷取我的公衆号半年前的文章,能否擷取每個文章的所有資訊(比如标題、封面、标簽)等。即scope。

注冊後,xx過來讓平台把我的文章資料都給xx,平台核實後确認xx合法。

咱們上節課講過,在授權碼許可類型中,授權服務的工作,可以劃分為兩大部分,一個是頒發授權碼code,一個是頒發通路令牌access_token。

授權服務是如何頒發授權碼和通路令牌的?(上)授權服務的工作過程頒發授權碼code流程

頒發授權碼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的值,即過程二。

繼續閱讀