oauth2.0授权协议中授权服务的功能及工作原理分析

本文深入探讨了OAuth2.0授权框架中的授权码流程,详细阐述了从用户授权到颁发访问令牌的步骤,包括验证基本信息、权限范围校验、生成授权码和访问令牌,以及令牌的校验和吊销。同时介绍了授权服务器的四个关键端点:授权端点、令牌端点、校验端点和吊销端点,阐述了它们在授权过程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

授权这个大动作的前提,肯定是第三方软件要去平台那里“备案”,也就是注册。注册完后,开放平台就会给第三方软件app_id和app_secret等信息,以方便后面授权时的各种身份校验。

同时,注册的时候,第三方软件也会请求受保护资源的可访问范围。

授权服务可以说是整个OAuth 2.0体系中的 “灵魂” 组件,任何一种许可类型都离不开它的支持,它也是最复杂的组件。它将复杂性尽可能地“揽在了自己身上”,才使得第三方软件接入OAuth 2.0的时候更加便捷。

授权服务器组成

提供4个端点 endpoint

  1. Authorize Endpoint:授权端点

    授权端点,颁发授权码code

  2. Token Endpoint:令牌端点

    经过授权之后,颁发access_token

  3. Introspection Endpoint:校验端点

    主要是资源服务器,拿到token之后,要通过访问授权服务器校验这个token是不是合法

  4. Revocation Endpoint:吊销端点

先看授权服务提供服务的两个重要端点:负责生成授权码的授权端点以及负责颁发访问令牌的令牌端点。下图是这两个端点的实现细节。
在这里插入图片描述

功能1:颁发授权码code

授权服务需要完成两部分工作,分别是准备工作生成授权码code

准备工作

在用户看到这个授权页面之前,实际上已经做了一系列动作。

包括验证基本信息、验证权限范围(第一次)和生成授权请求页面这三步。

1. 验证基本信息

对第三方软件合法性和回调地址合法性的校验

com.oauth.ch03.OauthServlet#doGet

if(!appMap.get("app_id").equals(appId)){
    return;
}

if(!appMap.get("redirect_uri").equals(redirectUri)){
    return;
}

2. 验证权限范围(第一次)

当用户为第三方软件进行授权的时候,也可以选择给第三方软件的权限范围,比如是否授予第三方软件获取3个月以前的订单的访问权限。

需要对第三方软件传过来的scope参数,与第三方软件注册时申请的权限范围做比对。如果请求过来的权限范围大于注册时的范围,就需要作出越权提示。记住,此刻是第一次权限校验。

//验证第三方软件请求的权限范围是否与当时注册的权限范围一致
if(!checkScope(scope)){
    //超出注册的权限范围
    return;
}

在授权服务的程序中,这两步验证通过后,就会生成或者响应一个页面(属于授权服务器上的页面),以提示用户进行授权。

3. 生成授权请求页面

在这里插入图片描述
页面上显示了第三方软件注册时申请的today、history 两种权限,用户可以选择缩小这个权限范围,比如仅授予获取today信息的权限。

登录和授权是两个通路的事情,任何授权都是在用户登录之后进行的。

在上面的准备过程中,我们忽略了用户登录的过程,但只有用户登录了才可以对第三方软件进行授权,授权服务才能够获得用户信息并最终生成code 和 app_id(第三方软件的应用标识) + user(资源拥有者标识)之间的对应关系。

生成授权码code

用户点击“approve”按钮之后,生成授权码code的流程就正式开始了,主要包括验证权限范围(第二次)、处理授权请求生成授权码code和重定向至第三方软件这三大步。

4. 验证权限范围(第二次)

这相当于一次用户的输入权限。用户选择了一定的权限范围给到授权服务,对于权限的校验我们要重视对待,凡是输入性数据都会涉及到合法性检查。

if(!checkScope(rscope)){//验证权限范围,对又验证一次
    //超出注册的权限范围
    System.out.println("out of scope ...");
    return;
}

r是replay

5. 处理授权请求,生成授权码code

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时使用。

String code = generateCode(appId,"USERTEST");//模拟登陆用户为USERTEST
private String generateCode(String appId,String user) {
    Random r = new Random();
    StringBuilder strb = new StringBuilder();
    for (int i = 0; i < 8; i++) {
        strb.append(r.nextInt(10));
    }
    String code = strb.toString();

    codeMap.put(code,appId+"|"+user+"|"+System.currentTimeMillis());//在这一篇章我们仅作为演示用,实际这应该是一个全局内存数据库,有效期官方建议是10分钟

    return code;
}

OAuth 2.0规范建议授权码code值有效期为10分钟,并且一个授权码code只能被使用一次。不过根据经验呢,在生产环境中code的有效期一般不会超过5分钟。

同时,授权服务还需要将生成的授权码code跟已经授权的权限范围rscope进行绑定并存储,以便后续颁发访问令牌时,我们能够通过code值取出授权范围并与访问令牌绑定。

codeScopeMap.put(code,rscope);//授权范围与授权码做绑定

6. 重定向至第三方软件

String toAppUrl = URLParamsUtil.appendParams(redirectUri,params);//构造第三方软件的回调地址,并重定向到该地址

response.sendRedirect(toAppUrl);//授权码流程的【第二次】重定向

功能2:颁发访问令牌access_token

这个过程主要包括验证第三方软件第三方软件是否存在、验证code值是否合法和生成access_token值这三大步。

1. 验证第三方软件第三方软件是否存在

接收到的grant_type的类型为authorization_code

由于颁发访问令牌是通过后端通信完成的,所以这里除了要校验app_id外,还要校验app_secret。

//处理授权码流程中的 颁发访问令牌 环节
if("authorization_code".equals(grantType)){
    if(!appMap.get("app_id").equals(appId)){
        response.getWriter().write("app_id is not available");
        return;
    }

    if(!appMap.get("app_secret").equals(appSecret)){
        response.getWriter().write("app_secret is not available");
        return;
    }
}

2. 验证code值是否合法

code值对应的key是app_id和user的组合值

String code = request.getParameter("code");

if(!isExistCode(code)){//验证code值
    return;
}
codeMap.remove(code);//授权码一旦被使用,须要立即作废

3. 生成access_token值

符合三个原则:唯一性、不连续性、不可猜性

和授权码code值一样,

  • 需要将访问令牌access_token值存储起来,并将其与第三方软件的应用标识app_id和资源拥有者标识user进行关系映射。
  • 授权服务还需要将授权范围跟访问令牌access_token做绑定
  • 需要为该访问令牌设置一个过期时间expires_in
String accessToken = UUID.randomUUID().toString();

String expires_in = "1";//1天时间过期

tokenMap.put(accessToken,appId+"|"+user+"|"+System.currentTimeMillis()+"|"+expires_in);//在这一篇章我们仅作为演示用,实际这应该是一个全局数据库,并且有有效期

功能3:校验令牌

主要是资源服务器,拿到token之后,要通过访问授权服务器校验这个token是不是合法

功能4:吊销令牌

  • 授权服务器发现access_token已经泄露了,可以吊销
  • 用户取消授权或修改密码,可以吊销
  • 第三方软件是付费软件,有效期到了,主动吊销

授权码流程中的请求和响应

功能1:生成授权码的授权端点

请求参数
在这里插入图片描述
响应参数
在这里插入图片描述

功能2:颁发访问令牌的令牌端点

请求参数
在这里插入图片描述
响应参数
在这里插入图片描述

更多内容,参考:oauth2.0开发总结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值