过程二:颁发访问令牌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。
至此,授权码许可类型下授权服务的两大主要过程,也就是颁发授权码和颁发访问令牌的流程,我就与你讲完了。
颁发授权码和颁发访问令牌,就是授权服务的核心。