前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >授权服务是如何颁发授权码和访问令牌的?

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

作者头像
JavaEdge
修改于 2025-06-10 00:13:39
修改于 2025-06-10 00:13:39
3.2K0
举报
文章被收录于专栏:JavaEdgeJavaEdge

本文已收录在Github关注我,紧跟本系列专栏文章,咱们下篇再续!

  • 🚀 魔都架构师 | 全网30W技术追随者
  • 🔧 大厂分布式系统/数据中台实战专家
  • 🏆 主导交易系统百万级流量调优 & 车联网平台架构
  • 🧠 AIGC应用开发先行者 | 区块链落地实践者
  • 🌍 以技术驱动创新,我们的征途是改变世界!
  • 👉 实战干货:编程严选网

0 前言

授权服务如何生成访问令牌?

访问令牌过期了而用户又不在场的情况下,又如何重新生成访问令牌?

1 授权服务的工作过程

xx让我去公众号开放平台给它授权数据时,你是否好奇?开放平台咋知道 xx 是谁?他合法备案了吗?病毒软件咋办?

所以,授权前提是xx要去开放平台备案,即注册。之后,开放平台就会给xx软件app_idapp_secret等,方便后续授权时的各种校验。

注册时,三方软件也会请求受保护资源的可访问范围。如xx能否获取我的公众号半年前的文章,能否获取每个文章的所有信息(比如标题、封面、标签)等。即scope。

注册后,xx过来让平台把我的文章数据都给xx,平台核实后确认xx合法。

上文说过,授权码许可类型中,授权服务的工作,可划分两大部分:

  • 颁发授权码code
  • 颁发访问令牌access_token

2 颁发授权码code的流程

2.1 过程一:颁发授权码code

授权服务负责准备工作和生成授权码code。

① 准备工作

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

验证基本信息

Web颁发code的整个请求过程,都通过浏览器由前端通信完成,即所有信息都可能被伪造,如回调地址,将其伪装成钓鱼页面,授权服务需要对回调地址做基本校验。

授权服务须对三方软件的存在性判断:

代码语言:java
AI代码解释
复制
if(!appMap.get("redirect_uri").equals(redirectUri)) {
    // 回调地址不存在
}

授权服务程序中,这两步验证通过后,会生成或响应一个页面(授权服务器上的页面),提示小明进行授权。

② 验证权限范围(第一次)

授权范围。如用微信登录三方软件时,微信提示我们,三方软件可获得你的昵称、头像、性别、地理位置等。如你不想让它们获取你的某信息,可不选择该项。

对xx传过来的scope参数,与小兔注册时申请的权限范围对比。

第一次权限校验:

代码语言:java
AI代码解释
复制
String scope = request.getParameter("scope");
if(!checkScope(scope)) {
    // 超出注册的权限范围
}
③ 生成授权请求页面

即授权服务上的页面,页面上显示注册时申请的权限,我可选择缩小这个权限范围。

至此,颁发授权码code准备工作完成。当用户点击授权按钮“approve”后,才会生成授权码code值和访问令牌acces_token

只有用户登录了才可对三方软件授权,授权服务才能够获得用户信息并最终生成code 和 app_id(第三方软件的应用标识) + user(资源拥有者标识)之间的对应关系。

我扫码同意后,生成授权码code的流程开始,主要包括:

  • 验证权限范围(第二次)
  • 处理授权请求生成授权码code
  • 重定向至第三方软件
④ 验证权限范围(第二次)

步骤②生成授权页面前授权服务进行的第一次校验,是对比xx请求的权限范围和注册时的权限。

为啥还校验一次?

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

代码语言:java
AI代码解释
复制
String[] rscope =request.getParameterValues("rscope");

if(!checkScope(rscope)) {
    // 超出注册的权限范围
}
⑤ 处理授权请求,生成授权码code

我同意授权后,授权服务会校验响应类型response_type的值。response_type有code和token两种类型的值。

用授权码流程举例,因此代码要验证response_type的值是否为code。

代码语言:java
AI代码解释
复制
String responseType = request.getParameter("response_type");
if("code".equals(responseType)) {
  ...
}

授权服务中,需要将生成的授权码code值与app_id、user进行关系映射。即一个授权码code,表示某用户给某三方软件授权。同时要将code和这种映射关系保存,以便在生成访问令牌access_token时使用。

代码语言:java
AI代码解释
复制
// 模拟登录用户为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值取出授权范围并与访问令牌绑定。因三方软件最终是通过访问令牌来请求受保护资源。

代码语言:java
AI代码解释
复制
Map<String,String[]> codeScopeMap =  new HashMap<String, String[]>();

codeScopeMap.put(code,rscope);//授权范围与授权码做绑定
⑥ 重定向至三方软件

生成授权码code后,授权服务需要将该code值告知第三方软件。

颁发授权码code是前端通信完成,因此这里采用重定向。即第二次重定向

代码语言:java
AI代码解释
复制
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的值,即过程二。

2.2 过程二:颁发访问令牌access_token

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

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

① 验证第三方软件是否存在

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

代码语言:java
AI代码解释
复制
String grantType = request.getParameter("grant_type");
if("authorization_code".equals(grantType)){
  
}

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

代码语言:java
AI代码解释
复制
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的组合值。

代码语言:java
AI代码解释
复制
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。

代码语言:java
AI代码解释
复制
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

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

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

3 刷新令牌

为何需要刷新令牌?

在生成访问令牌的时附加过期时间expires_in

访问令牌会在一定的时间后失效。访问令牌失效,资源拥有者给第三方软件的授权失效,第三方软件无法继续访问资源拥有者的受保护资源。

如果还想继续使用三方软件,必须重新点击授权按钮,比如我给xx授权后,正在愉快地编写我公众号的文章呢,刚准备使用 xx 的导入文章功能,突然xx再次让我进行授权。此刻,我可很崩溃!

于是,OAuth 2.0中引入刷新令牌,即刷新访问令牌access_token的值。有了刷新令牌,用户在一定期限内无需重新授权,就可继续使用三方软件。

刷新令牌的原理

刷新令牌也是给第三方软件使用的,同样需要遵循先颁发再使用的原则。

颁发刷新令牌

颁发刷新令牌和颁发访问令牌一起实现,都在过程二的步骤三生成访问令牌access_token中生成的。即第三方软件得到一个访问令牌的同时,也会得到一个刷新令牌:

代码语言:java
AI代码解释
复制
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的值。

这其中的流程主要包括如下两大步骤。

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

请求中的grant_type值为refresh_token。

代码语言:java
AI代码解释
复制
String grantType = request.getParameter("grant_type");
if("refresh_token".equals(grantType)){
  
}

和颁发访问令牌前的验证流程一样,也要验证第三方软件是否存在。这里需同时验证刷新令牌是否存在,目的就是要保证传过来的刷新令牌的合法性。

代码语言:java
AI代码解释
复制
String refresh_token = request.getParameter("refresh_token");

if(!refreshTokenMap.containsKey(refresh_token)){
    //该refresh_token值不存在
}

另外,我们还需要验证刷新令牌是否属于该第三方软件。授权服务是将颁发的刷新令牌与第三方软件、当时的授权用户绑定在一起的,因此这里需要判断该刷新令牌的归属合法性。

代码语言:java
AI代码解释
复制
String appStr = refreshTokenMap.get("refresh_token");
if(!appStr.startsWith(appId+"|"+"USERTEST")){
    //该refresh_token值不是颁发给该第三方软件的
}

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

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

生成访问令牌的处理流程,与颁发访问令牌环节的生成流程一致。授权服务会将新的访问令牌和新的刷新令牌,一起返回给第三方软件。

4 总结

授权服务的核心:先颁发授权码code值,再颁发访问令牌access_token值。

颁发访问令牌同时,还会颁发刷新令牌refresh_token值,这种机制可在无需用户参与case下用于生成新的访问令牌。正如小明使用小兔软件的例子,当访问令牌过期,刷新令牌的存在可大大提高小明使用小兔软件的体验。

授权还要有授权范围,不能让第三方软件获得比注册时权限范围还大的授权,也不能获得超出了用户授权的权限范围,始终确保最小权限安全原则

5 FAQ

Q:若access_token未超时,则进行refresh_token有啥方式?

A:两种:

  1. 不会改变access_token,但超时时间会刷新,相当于续期access_token
  2. 更新access_token的值,我们建议【统一更新access_token的值】。

延期access_token并非最好方式,尽管有的开放平台是这么做。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/10/19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
SSH 远程连接中断 导致阿里云服务器程序运行终止解决方法
关于其他操作参见:https://blog.csdn.net/ancient_wind/article/details/7989015
圆号本昊
2021/09/24
3.1K0
SSH 远程连接中断 导致阿里云服务器程序运行终止解决方法
高效简单的服务器登录配置
当你拥有了属于自己的一个云服务器后,首先需要做的事情就是登录服务器。而登录服务器,作为新手可以通过云厂商提供的 dashboard 进行登录操作。但是,最简单及最方便的方式还是通过终端,使用 ssh 命令快速登录
山月
2020/05/25
1.5K0
Fix SSH客户端登录会话超时设置
通常默认公有云上的ECS远程连接,很容易断开,当你有什么事情被打断或者去操作别的机器同步做点其他事情,你会发现你SSH客户端登录窗口经常会断开掉,非常烦人,经常要重新登录。
后场技术
2020/09/03
5.8K0
Fix SSH客户端登录会话超时设置
防止ssh登录服务器的掉线
因为云服务器是我自己的,而要给十几个新手使用,所以我应该使用root权限来选择修改sshd_config文件里面的服务端参数,这样才能做到一次修改,终身受益!!!
生信技能树
2018/12/05
2.4K0
配置SSH服务远程连接空闲超时退出时间(包括SSH无法登录、登录缓慢)
编辑/etc/ssh/sshd_config配置文件,将ClientAliveInterval设置为300到900,即5-15分钟,将ClientAliveCountMax设置为0。
非著名运维
2022/06/22
9.2K0
linux ssh 登录后 空闲断开 解决方法
我们通过终端连接服务器时,当鼠标和键盘长时间不操作,服务器就会自动断开连接,我们还的需要重新连接,感觉很麻烦,总结一下解决此问题的方法
IT工作者
2022/07/28
3.1K0
配置服务器的免密码快捷登录
ssh,secure shell protocol,以更加安全的方式连接远程服务器。
山月
2022/11/02
3.5K0
配置服务器的免密码快捷登录
如何让计算机工作环境更便捷?几行简单的命令即可
过去几年里,我一直从事数据科学/研究项目,本科就做了一些与这个行业相关的工作,现在是研究生在读,也在做这方面的研究。作为一个喜欢便捷环境的人,我总是喜欢改进我的工作方式,将日常的枯燥过程变得「自动化」。在这篇文章中,我将描述如何使环境更便于使用。
机器之心
2019/05/07
6880
如何让计算机工作环境更便捷?几行简单的命令即可
保持SSH连接持续不断的配置方法
在修改服务器的一些文件的过程中,经常碰到的情况就是需要隔一段时间修改一下文件,然后需要去查阅相关的资料,等下一次想修改的时候发现ssh连接由于长时间未相应已经断开了。而且这时候终端会卡在那里,十分的不方便。所以在网上找了几个配置SSH的方法,能保证连接能够长时间不断开。 方法有两种,一般配置一种就可以。但是我为了效果更好,把他们同时配置一下:
mythsman
2022/11/14
2.1K0
mac终端如何自定义登录欢迎语
shigen看着单调的终端,突然有了一丝丝的念头,我要搞的炫酷一点。让我想到的一个场景就是:我之前在使用公司的阿里云服务器的时候,在每次登录的时候会有欢迎语,类似于这样的:
shigen
2023/12/26
3020
mac终端如何自定义登录欢迎语
Linux系统相关配置
Linux系统安装好以后,我们需要对这个系统进行简单的配置,其中主要包括以下几部分的内容:
以某
2023/03/07
2.4K0
如何用macOS玩转Linux? macOS配置Paralles 安装的 ubuntu20.04 arm64 并通过iTerm ssh自动操作虚拟机
作为一个开发者,如果想要搞一些自己的项目,就要对Linux有一些了解,而学习Linux的最好方式,就是充分使用它,Windows通过WSL,已经完美支持Linux子系统,那macOS如何玩转Linux?
zhaoolee
2022/10/04
2.9K0
如何用macOS玩转Linux? macOS配置Paralles 安装的 ubuntu20.04 arm64 并通过iTerm ssh自动操作虚拟机
mac系统ssh远程登录服务器小清新方案
Windows下有xshell,puty等一系列ssh软件,免费又好用,mac则没有。mac下虽然有SecureCrt,ZOC Terminal,但都还是收费的,虽说有破解版,但是版本落后不说,破解起来也麻烦。 经过本人一系列的研究,最终整出一套比较好用的方案,利用Shuttle+iTerm+ SSHPass来实现,这套方案清爽、轻便且实用。
皇上得了花柳病
2020/05/06
1.2K0
mac系统ssh远程登录服务器小清新方案
Linux | 如何保持 SSH 会话处于活动状态
在远程服务器管理和安全数据传输中,SSH(Secure Shell)是不可或缺的工具。然而,它的便利性和安全性有时会因常见的问题而受到损害:冻结 SSH 会话。
数据科学工厂
2023/11/02
2.2K0
Linux | 如何保持 SSH 会话处于活动状态
linux自定义SSH连接以简化远程访问
SSH (SSH client) 是一个远程访问服务器的程序,它使用户能够在远程主机上执行命令。它是最推荐的远程登录主机的方法之一,因为它旨在通过不安全的网络在两个不受信任的主机之间提供安全的加密通信。 SSH使用系统范围和用户特定(自定义)配置文件。在本教程中,我们将解释如何创建自定义ssh配置文件并使用某些选项连接到远程主机。 SSH 客户端配置文件 ssh客户端配置文件的位置: /etc/ssh/ssh_config这是默认的、系统范围的配置文件。它包含适用于ssh客户端计算机的所有用户的设置。 ~/
入门笔记
2022/06/02
1.7K0
如何保持SSH连接的linux服务器不断线
使用SecureCRT连接远程服务器,在会话选项 -> 终端设置中勾选“发送协议 NO-OP”。
明哥的运维笔记
2019/01/30
3.9K0
如何保持SSH连接的linux服务器不断线
解决SSH连接Linux超时
在开发当中经常需要登录远程服务器,于是通过 ssh 或者 putty 登录,可是一转身,这厮就自动断开了。让人非常恼火,如何解决 SSH 连接 Linux 超时自动断开?
chuchur
2022/10/25
10K0
SSH——云服务器SSH经常断开如何处理
基于安全考虑,云服务器的 ~c SSH Server c~ 闲置一段时间会自动断开,不过这个闲置的一段时间说实话太短了,很容易断开,所以改造下吧; 客户端: SCRT
思索
2024/08/15
4620
Mac电脑iTerm2链接Linux服务器断线解决方案
用Windows链接Linux服务器,方式很多,我最经常用的是xshell。但是xshell没有mac版,那用mac电脑,比较好的命令行软件是什么呢?我用的是iTerm2 ,这个功能确实蛮强大,很多人都在用。但是,你用iTerm2 链接远程Linux服务器,假如你去干别的,一会再回到iTerm2 ,你会发现iTerm2 断线了,苦逼的还要再次进行链接,好麻烦!针对这个有没有什么好的解决方案呢?
星哥玩云
2022/07/24
2.5K0
解决macOS下ssh空闲一段时间自动断开的问题
使用ssh登录linux服务器后,在后台放置一段时间,会发现会自动断开或者卡死无法输入
Huramkin
2018/09/17
4K0
推荐阅读
相关推荐
SSH 远程连接中断 导致阿里云服务器程序运行终止解决方法
更多 >
LV.2
Java开发工程师
目录
  • 0 前言
  • 1 授权服务的工作过程
  • 2 颁发授权码code的流程
    • 2.1 过程一:颁发授权码code
      • ① 准备工作
      • ② 验证权限范围(第一次)
      • ③ 生成授权请求页面
      • ④ 验证权限范围(第二次)
      • ⑤ 处理授权请求,生成授权码code
      • ⑥ 重定向至三方软件
    • 2.2 过程二:颁发访问令牌access_token
      • ① 验证第三方软件是否存在
      • ② 验证授权码code值是否合法
      • ③ 生成访问令牌access_token值
  • 3 刷新令牌
    • 为何需要刷新令牌?
    • 刷新令牌的原理
    • 颁发刷新令牌
      • 为什么要一起生成访问令牌和刷新令牌
    • 使用刷新令牌
      • 第一步-接收刷新令牌请求,验证基本信息
      • 第二步,重新生成访问令牌
  • 4 总结
  • 5 FAQ
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档