天天看点

授权服务是如何颁发授权码和访问令牌的?(中)

过程二:颁发访问令牌access_token

xx最终要获取访问令牌access_token,才可请求受保护资源。而授权码只是一个换取访问令牌access_token的临时凭证。

当小兔拿着授权码code来请求的时候,授权服务需要为之生成最终的请求访问令牌。

第一步,验证第三方软件是否存在

此时,接收到的grant_type的类型为authorization_code。

String grantType = request.getParameter("grant_type");
if("authorization_code".equals(grantType)){
  
}      

颁发访问令牌是后端完成,所以校验app_id、app_secret。

if(!appMap.get("app_id").equals(appId)){
    //app_id不存在
}

if(!appMap.get("app_secret").equals(appSecret)){
    //app_secret不合法
}      

第二步-验证授权码code值是否合法

授权服务在颁发授权码code的阶段已存储code值,此时对比从request中接收到的code值和从存储中取出来的code值。在我们给出的课程相关代码中,code值对应的key是app_id和user的组合值。

String code = request.getParameter("code");
if(!isExistCode(code)){//验证code值
    //code不存在
  return;
}
codeMap.remove(code);//授权码一旦被使用,须立即作废      

确认过授权码code值有效后,应立刻从存储中删除当前code值,以防止第三方软件恶意使用一个失窃的授权码code值来请求授权服务。

第三步-生成访问令牌access_token值

OAuth 2.0规范规定必须符合三个原则:唯一性、不连续性、不可猜性。UUID可考虑来作为示例的。

和授权码code值一样,需要存储访问令牌access_token值,并将其与三方软件应用标识app_id和资源拥有者标识user映射。也就是说,一个访问令牌access_token表示某一个用户给某一个第三方软件进行授权。

同时,授权服务还需要将授权范围跟访问令牌access_token做绑定。最后要为该访问令牌设置一个过期时间expires_in。

Map<String,String[]> tokenScopeMap =  new HashMap<String, String[]>();

String accessToken = generateAccessToken(appId,"USERTEST");//生成访问令牌access_token的值
tokenScopeMap.put(accessToken,codeScopeMap.get(code));//授权范围与访问令牌绑定

//生成访问令牌的方法
private String generateAccessToken(String appId,String user){
  
  String accessToken = UUID.randomUUID().toString();
    String expires_in = "1";//1天时间过期
  tokenMap.put(accessToken,appId+"|"+user+"|"+System.currentTimeMillis()+"|"+expires_in);

  return accessToken;
}      

OAuth 2.0没有约束访问令牌内容的生成规则,可以生成一个UUID存储,让授权服务和受保护资源共享该数据,也可将一些必要信息通过结构化处理放入令牌本身。我们将包含一些信息的令牌,称为结构化令牌,简称JWT。

至此,授权码许可类型下授权服务的两大主要过程,也就是颁发授权码和颁发访问令牌的流程,我就与你讲完了。

颁发授权码和颁发访问令牌,就是授权服务的核心。