03 | 授权服务:授权码和访问令牌的颁发流程是怎样的? 笔记

news2025/7/21 1:11:26

03 | 授权服务:授权码和访问令牌的颁发流程是怎样的?

授权服务的工作过程

小兔软件需要去到京东的平台那里”备案“注册,京东商家开放平台就会给小兔软件 app_id 和 app_secret 等信息,以方便后面授权时的各种身份校验,也会有请求资源的访问范围,比如只能访问3个月内的订单数据。
代码:


Map<String,String> appMap =  new HashMap<String, String>();//模拟第三方软件注册之后的数据库存储

appMap.put("app_id","APPID_RABBIT");
appMap.put("app_secret","APPSECRET_RABBIT");
appMap.put("redirect_uri","http://localhost:8080/AppServlet-ch03");
appMap.put("scope","nickname address pic");

授权服务的工作,可以划分为 颁发授权码 code、颁发访问令牌 access_token。
image.png

过程一:颁发授权码 code

在用户进行授权操作的时候,需要进行一些准备的工作。

第一步,验证基本信息

授权服务需要对回调地址做基本的校验,这个回调地址在client注册时就已经提供,因此可以检查是否被替换。(因为有些非法的请求,可能会伪造回调地址,钓鱼之类的)


if(!appMap.get("redirect_uri").equals(redirectUri)){
    //回调地址不存在
}

第二步,验证权限范围(第一次)。

第三方软件可以获得你的昵称、头像、性别、地理位置等. 比如是否授予小兔获取 3 个月以前的订单的访问权限。
第一次权限校验


String scope = request.getParameter("scope");
if(!checkScope(scope)){
    //超出注册的权限范围
}

第三步,生成授权请求页面。

授权服务上的页面
image.png

第四步,验证权限范围(第二次)。

第二次校验主要是用户选择的权限范围,我们也需要校验,判断是否合理。


String[] rscope =request.getParameterValues("rscope");

if(!checkScope(rscope)){
    //超出注册的权限范围
}

第五步,处理授权请求,生成授权码 code。

当小明同意授权之后,授权服务会校验响应类型 response_type 的值


String responseType = request.getParameter("response_type");
if("code".equals(responseType)){
  
}

在授权服务中,需要将生成的授权码 code 值与 app_id、user 进行关系映射,比如小明给小兔软件进行的授权

String code = generateCode(appId,"USERTEST");//模拟登录用户为USERTEST

private String generateCode(String appId,String user) {
  ...
  String code = strb.toString();
  codeMap.put(code,appId+"|"+user+"|"+System.currentTimeMillis());
  return code;
}

OAuth 2.0 规范建议授权码 code 值有效期为 10 分钟,并且一个授权码 code 只能被使用一次授权服务还需要将生成的授权码 code 跟已经授权的权限范围 rscope 进行绑定并存储

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

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

第六步,重定向至第三方软件。

生成授权码 code 值之后,授权服务需要将该 code 值告知第三方软件小兔.这个是前端的操作,重定向

Map<String, String> params = new HashMap<String, String>();
params.put("code",code);

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

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

过程二:颁发访问令牌 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 值存储了起来.所以我们只需要校验

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

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

第三步,生成访问令牌 access_token 值。

access_token 的值原则:唯一性、不连续性、不可猜性
个访问令牌 access_token 表示某一个用户给某一个第三方软件进行授权。授权服务还需要将授权范围跟访问令牌 access_token 做绑定。

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;
}

信息通过结构化的处理放入令牌本身。我们将包含了一些信息的令牌,称为结构化令牌,简称 JWT。

刷新令牌

比如令牌10分钟之后过期,总不能让用户10分钟再授权一次吧,所以就需要续约,刷新。
其实,颁发刷新令牌和颁发访问令牌是一起实现的,都是在过程二的步骤三生成访问令牌 access_token 中生成的。

Map<String,String> refreshTokenMap =  new HashMap<String, String>();

String refreshToken = generateRefreshToken(appId,"USERTEST");//生成刷新令牌refresh_token的值

private String generateRefreshToken(String appId,String user){

  String refreshToken = UUID.randomUUID().toString();

  refreshTokenMap.put(refreshToken,appId+"|"+user+"|"+System.currentTimeMillis());
  return refreshToken;
  
} 

访问令牌失效了,就使用刷新令牌。

使用刷新令牌

在 OAuth 2.0 规范中,刷新令牌是一种特殊的授权许可类型,是嵌入在授权码许可类型下的一种特殊许可类型。

第一步,接收刷新令牌请求,验证基本信息。

此时请求中的 grant_type 值为 refresh_token。

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

使用刷新令牌也是需要校验合法性,


String grantType = request.getParameter("grant_type");
if("refresh_token".equals(grantType)){
  //该refresh_token值不存在
}

if(!appStr.startsWith(appId+"|"+"USERTEST")){
    //该refresh_token值不是颁发给该第三方软件的
}

需要注意,一个刷新令牌被使用以后,授权服务需要将其废弃,并重新颁发一个刷新令牌

第二步,重新生成访问令牌

总结

  1. 授权服务的核心就是,先颁发授权码 code 值,再颁发访问令牌 access_token 值。
  2. 在颁发访问令牌的同时还会颁发刷新令牌 refresh_token 值,这种机制可以在无须用户参与的情况下用于生成新的访问令牌。
  3. 授权还要有授权范围,不能让第三方软件获得比注册时权限范围还大的授权,也不能获得超出了用户授权的权限范围,始终确保最小权限安全原则。

若access_token未超时,那么进行refresh_token有两种方式,
(1)不会改变access_token,但超时时间会刷新,相当于续期access_token
(2)更新access_token的值,我们建议【统一更新access_token的值】。(不可以让“token一个更长的有效期”存在的)
原文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/395293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

scratch绘制雷达 电子学会图形化编程scratch等级考试三级真题和答案解析2022年9月

目录 scratch绘制雷达 一、题目要求 1、准备工作 2、功能实现 二、案例分析

阶段二12_面向对象高级_继承1

一.继承的入门介绍 (1)继承的概念理解 让类与类之间产生关系&#xff08;子父类关系&#xff09;&#xff0c;子类可以直接使用父类中非私有的成员 (2)通过extends关键字实现继承 格式&#xff1a;public class 子类名 extends 父类名 { } 范例&#xff1a;public class Zi e…

Grafana 如何使用本地CSV文件作为数据源

Grafana提供了一个插件&#xff0c;可以把CSV文件作为数据源&#xff0c;关于CSV插件的说明&#xff0c;可以参考&#xff1a;https://grafana.com/grafana/plugins/marcusolsson-csv-datasource/?tabinstallation。我是在本地使用命令行grafana-cli plugins install marcusol…

通过45人!1-2月,誉天红帽RHCE学员再创佳绩!

学习的喜悦在于结果&#xff0c;也在于过程&#xff1b;在于取得成功时的豁然开朗&#xff0c;也在于持之以恒后的层层递进。结果固然重要&#xff0c;但在求知过程中获得的满足感&#xff0c;也同样让人乐在其中。 RHCE的学习过程就充满了这样的喜悦。对每一行命令的理解、对每…

【Linux学习】日积月累——调试器gdb的使用教程

一、背景 gdb是一款强大的命令行调试工具&#xff0c;可以形成执行程序、脚本。只需要几个简单的命令&#xff0c;就能够实现Windows环境下VC等IDE的图形化调式工具的功能。 调试的相关常识&#xff1a; 程序的发布方式有两种&#xff0c;debug模式和release模式&#xff1b;L…

197.Spark(四):Spark 案例实操,MVC方式代码编程

一、Spark 案例实操 1.数据准备 电商网站的用户行为数据,主要包含用户的 4 种行为:搜索,点击,下单,支付 样例类: 2. Top10 热门品类 先按照点击数排名,靠前的就排名高;如果点击数相同,再比较下单数;下单数再相同,就比较支付数。 我们有多种写法,越往后性能越…

【Linux开发笔记】《Linux嵌入式开发从0到1》(一):初探Linux——与Linux的初次相遇

1.什么是Linux Linux就是一个操作系统&#xff0c;就是一个开源、自由的操作系统&#xff0c;就是一个免费使用和自由传播的类UNIX操作系统&#xff0c;就是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。 简单来讲&#xff0c;Linux就是一个操作系统而已… …

React的Hooks

React Hooks useState useMemo 和usecallback Hooks显示的指明因变量有什么好处 当使用时&#xff0c;y与changeX会被缓存下来&#xff0c;只要x不变&#xff0c;始终读取的是缓存的值&#xff0c; 如果不使用时&#xff0c;每次函数组件执行时&#xff0c;实际会基于x&#xf…

计算机写论文时,怎么引用文献? - 易智编译EaseEditing

首先需要清楚哪些引用必须注明[1]&#xff1a; 任何直接引用都要用引号并注明来源&#xff1b; 任何不是自己的口头或书面的观点、解释和结论都应注明来源&#xff1b; 即使不用原话&#xff0c;但是他人的思路、概念或观点也应注明&#xff1b; 不要为了适合你的观点修改原…

机器学习——无监督学习

机器学习的分类一般分为下面几种类别&#xff1a;监督学习( supervised Learning )无监督学习( Unsupervised Learning )强化学习( Reinforcement Learning&#xff0c;增强学习)半监督学习( Semi-supervised Learning )深度学习(Deep Learning)Python Scikit-learn. http: // …

day40|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个…

软件测试8

一 缺陷 软件缺陷&#xff1a;是指软件或程序中存在的各种问题及错误&#xff0c;会导致软件产品在某种程度上不能满足用户的需求 二 软件缺陷的判定标准 1.软件未达到需求规格说明书中表明的功能 2.软件出现了需求规格说明书不会出现错误的地方 3.软件的功能超出了需求规格…

14 nuxt3学习(布局 渲染模式 插件plugin 生命周期)

布局 布局是围绕包含多个页面的公共用户界面的页面的包装器&#xff0c;例如页眉和页脚显示。 布局是使用slot 组件显示页面内容的Vue文件。 默认情况下使用layouts/default.vue文件。 自定义布局可以设置为页面元数据的一部分。 方式一&#xff1a;默认布局 在layouts目录下…

Xmind快捷键大全

Xmind快捷键大全 1、常用 CtrlShiftL 快捷键助手CtrlHome 返回中心主题Enter 插入主题Tab 插入子主题F2 编辑主题F3 添加/编辑标签F4 添加/编辑备注F6 下钻ShiftF6 上钻Delete 删除Ctrl] 插入摘要CtrlI 插入图片CtrlShiftH 插入超链接Ctrl1,2,3,4,5,6快速添加优先等级图标Ctr…

applicationContext相关加载

spring refresh 概述 refresh是一个方法&#xff0c;spring中所有的ApplicationContext容器都需要通过refresh方法初始化&#xff1b; 处理步骤 其中refresh方法包含12个主要的处理步骤&#xff1a; 1、第1个步骤做前置准备 2、第2~6步骤创建BeanFactory&#xff08;Appl…

Java中垃圾回收(GC)算法详解

咱们要进行垃圾回收&#xff0c;是不是要知道哪些对象是垃圾&#xff0c;然后针对这些垃圾要怎么回收呢&#xff1f;那本篇文章我们就将垃圾回收分为标记垃圾、清除垃圾两个阶段讲解&#xff0c;详细说明每个阶段都有那些算法。1、标记阶段算法在堆里存放着几乎所有的Java对象实…

2023年交通与智慧城市国际会议(ICoTSC 2023)

2023年交通与智慧城市国际会议(ICoTSC 2023) 重要信息 会议网址&#xff1a;www.icotsc.org 会议时间&#xff1a;2023年7月28-30日 召开地点&#xff1a;长沙 截稿时间&#xff1a;2023年6月15日 录用通知&#xff1a;投稿后2周内 收录检索&#xff1a;EI,Scopus 会议简介…

轻松玩转开源大语言模型bloom(一)

前言 chatgpt已经成为了当下热门&#xff0c;github首页的trending排行榜上天天都有它的相关项目&#xff0c;但背后隐藏的却是openai公司提供的api收费服务。作为一名开源爱好者&#xff0c;我非常不喜欢知识付费或者服务收费的理念&#xff0c;所以便有决心写下此系列&#…

【Flutter】入门Dart语言:操作符的基本用法

文章目录 一、前言二、常用的操作符1.算术操作符2.关系操作符3.逻辑操作符4.赋值操作符5.三元运算符三、总结一、前言 当我们在编写Flutter应用程序时,操作符是我们不可或缺的工具。它们是用于执行各种操作的关键字和符号,可以帮助我们简化代码并提高效率。熟练掌握各种类型…

Tomcat在linux环境中开机自启(定时重启)

一、Tomcat开启自启 我们经常会遇到服务器断电或异常&#xff0c;而异常后tomcat中部署的web项目需要我手动去启动。为此&#xff0c;特别贡献出Linux环境中Tomcat开机自启的方式供学习使用。 1. 添加JAVA_HOME并配置tomcat自启 vi /etc/rc.local 添加如下语句&…