前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单点登录的实现(基于 OAuth2.0 协议)

单点登录的实现(基于 OAuth2.0 协议)

作者头像
阿龙w
发布2024-02-17 10:31:37
3160
发布2024-02-17 10:31:37
举报
文章被收录于专栏:阿龙的笔记阿龙的笔记

最近放假之后实现了一下单点登录,各种项目都需要账号管理系统,太麻烦了,导致各种项目都咕咕咕,懒得写(划掉)

OAuth 2.0 协议(本文简称 OAuth)是一种三方授权协议,目前大部分的第三方登录与授权都是基于该协议的标准或改进实现。OAuth 1.0 的标准在 2007 年发布,2.0 的标准则在 2011 年发布,其中 2.0 的标准取消所有 Token 的加密过程,并简化了授权流程,但因强制使用 HTTPS 协议,被认为安全性高于 1.0 的标准。

基本概念

在了解 OAuth 前,需先了解一下各个名词的基本概念

客户端:客户端是 OAuth 的接入方,目的是请求用户储存在资源服务器上的受保护资源。可以理解成前端应用(比如 Web、应用程序、小程序等)

用户代理(UA):用户参与互联网的工具,比如浏览器、系统标识等

资源所有者:受保护资源所属实体,比如资源持有人(就是你!!),下文用户即资源所有者

授权服务器:验证资源所有者身份的服务器,就是平时大家口中的 “登录服务器”

资源服务器:托管资源的服务器,能够接收和响应持有令牌的资源访问请求,可以理解成是客户端的后端程序

访问令牌:就是我们平时常说的 Token (Access Token),在用户(资源所有者)的授权许可下授权服务器下发给客户端的一个授权凭据,客户端(或资源服务器或任何人)可携带此令牌代表资源所有者的身份访问受保护的资源

刷新令牌:就是我们平时常说的 “双 Token”(Refresh Token),作用是在于更新访问令牌。访问令牌一般的时间较短,使用刷新令牌重新换取访问令牌,可以一定程度上减少对授权服务器和资源所有者的负担

回调地址:OAuth2.0 是一类基于回调的授权协议,以 302 重定向的形式,可以一定程度上简化客户端的操作

授权范围:用户可以指定该客户端能够访问的受保护资源的范围,比如个人纳税识别号、昵称、电邮地址等

授权流程

OAuth 协议已定义了 4 种授权模式(授权码模式、隐式授权模式、资源所有者密码凭证授权模式、客户端凭证授权模式),其中最具代表性的就是授权码模式,并且我也是使用这种模式授权的,所以本文就只讲解这种模式。如果需要了解其他模式,小米开放平台的文章中讲解的非常详细,可以前往观看,具体链接详见本文底部参考文献部分

授权码模式在整个授权流程上与 1.0 版本最贴近,但是整个流程还是要简化了许多,也是 OAuth2.0 中最标准,应用最广泛的授权模式。这类授权模式非常适合于具备服务端的应用,当然现在大多数 APP 都有自己的服务端,所以大部分 APP 的 OAuth 授权都可以采取授权码模式,下图为授权码各个角色之间的交互时序(这里让用户直接参与其中,省略了用户代理):

整个授权流程说明如下(具体参数释义见下文):

  1. 客户端携带 client_id, scope, redirect_uri, state 等信息引导用户请求授权服务器的授权端点下发 code
  2. 授权服务器验证客户端身份,验证通过则询问用户是否同意授权(此时会跳转到用户能够直观看到的授权页面,等待用户点击确认授权)
  3. 假设用户同意授权,此时授权服务器会将 code 和 state(如果客户端传递了该参数)拼接在 redirect_uri 后面,以302形式下发 code
  4. 客户端携带 code, redirect_uri, 以及 client_secret 请求授权服务器的令牌端点下发 access_token (这一步实际上中间经过了客户端的服务器,除了 code,其它参数都是在应用服务器端添加,下文会细讲)
  5. 授权服务器验证客户端身份,同时验证 code,以及 redirect_uri 是否与请求 code 时相同,验证通过后下发 access_token,并选择性下发 refresh_token

基于 Nya Account 的应用

创建应用

注意,此部分可能在实际中有所改动,具体请以 Nya Account 使用文档为准

访问 https://account.lolinya.net/ ,按照流程 登录 / 注册 账号

在应用管理中,选择创建应用,在弹出的模态框中,输入新应用的名称。该名称将会展示给用户。后续可修改。

随后点击应用列表操作栏中的查看详细按钮,配置应用的简介、重定向 URL 以及需要的权限,配置完成后需要点击保存按钮

目前程序为测试阶段,权限配置后期会逐渐增加

配置完后可在此处查看客户端 ID 和 客户端秘钥

获取授权码

授权码是授权流程的一个中间临时凭证,是对用户确认授权这一操作的一个暂时性的证书,其生命周期一般较短(协议建议最大不要超过10分钟),在这一有效时间周期内,客户端可以凭借该暂时性证书去授权服务器换取访问令牌

将用户 302 重定向到该地址

代码语言:javascript
复制
https://account.lolinya.net/authorize

并携带请求参数

参数名称

是否必须

描述信息

client_id

必须

客户端ID,用于标识一个客户端,在注册应用时生成(即 AppId)

state

推荐

用于维持请求和回调过程中的状态,防止CSRF攻击,服务器不对该参数做任何处理,如果客户端携带了该参数,则服务器在响应时原封不动的返回

redirect_uri

可选

授权回调地址(默认读取在注册应用时配置的)

scope

可选

权限范围,用于对客户端的权限进行控制,如果客户端没有传递该参数,那么服务器则以该应用的所有权限代替(所有权限默认读取在注册应用时配置的)

response_type

可选

对于授权码模式 response_type=code ,默认为此项,无需单独传递

用户在完成授权后,将会被重定向到创建应用时指定的地址,并携带请求参数(如果用户拒绝了授权,则 code=deny

名称

描述信息

code

授权码,授权码代表用户确认授权的暂时性凭证,只能使用一次,5分钟内有效

state

如果客户端传递了该参数,则原封不动返回

下发访问令牌

授权服务器在下发授权码之后,客户端或资源服务器,将携带刚刚下发的授权码请求以下地址

代码语言:javascript
复制
https://api.liyxi.com/node/v0/token

(中国大陆镜像服务器,很可能会变更,具体以使用文档为主)

携带请求体

名称

是否必须

描述信息

grant_type

必须

对于授权码模式 grant_type=authorization_code

code

必须

上一步骤获取的授权码

redirect_uri

必须

授权回调地址

client_id

必须

客户端 ID,用于标识一个客户端,等同于 appId ,在注册应用时生成

client_secret

必须

客户端秘钥,等同于 appSecret ,在注册应用时生成

type

可选

如果 type=info 则直接下发用户基础信息,而不是 token

正常情况下的响应体

名称

描述信息

access_token

访问令牌

token_type

访问令牌类型,比如 bearer,mac 等等

expires_in

访问令牌的生命周期,以秒为单位,表示令牌下发后多久时间过期

refresh_token

暂不开放,一般用户返回 refresh_token=null

scope

用户实际权限范围,如 [1,2,3,4] ,具体参见权限列表

如果 type=info ,则响应

名称

描述信息

uid

用户唯一标识符

nickname

用户昵称

status

用户当前在系统中的状态

avatar

用户头像 url

请求受保护的资源示例

比如需要获取用户信息,则携带刚刚下发的令牌访问

代码语言:javascript
复制
https://api.liyxi.com/node/v0/info

(中国大陆镜像服务器,很可能会变更,具体以使用文档为主)

响应体

json

代码语言:javascript
复制
{
  status: 200,
  msg: "获取用户基础信息成功",
  data: {}
}

data 如下

名称

类型

描述信息

uid

String

用户唯一标识符

nickname

String

用户昵称

status

Number

用户当前在系统中的状态

avatar

String

用户头像 url

对令牌相关知识的一些补充

在国内某短视频平台1中出现了可笑的一幕,这是一个关于 token 无感刷新的视频的评论区

令牌是由 header 、payload 、和 signature 三部分使用英文符号 “.” 连接而成的字符串(JWT)。在一般情况下,header 中存储的是此令牌的签名算法以及类型(base64 编码后),payload 中存储的是用户在使用 jwt 生成令牌时传入的数据(base64 编码后),signature 中存储的是使用前两者与特定的字符串秘钥加密后的字符串(签名),用于防篡改。对于 “长时间 token 会被破解” 这样的说法,几乎不可能,并且这也不是刷新令牌产生的根本原因。

关于令牌被劫持,在正常情况下,属于不可避免的原因或个人原因(比如在客户端或资源服务器上人为安装了病毒软件、第三者使用了漏洞)。在网络传输的过程中,TLS 拥有认证性、机密性、完整性以及重放保护,TLS 的基本工作方式是为客户端使用非对称加密与服务器进行通信,实现身份验证并协商对称加密使用的密钥,对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同的节点之间采用的对称密钥不同,从而可以保证信息只能通信双方获取,因此令牌绝大部分情况下不会在网络传输中被劫持

关于双令牌的形式,确实可以在一定程度上增加安全性,但是在实际中更多的是用于减轻授权服务器压力。举个例子,如用户张三2正在使用扣扣3账号游玩卑微斗农民4,张三在对局中连续打出了数个对子,如果客户端的每次一请求都需要经过授权服务器,则授权服务器必将承担非常大的压力,如果授权服务器出现故障,则会影响到所有存放受保护资源的服务器上的业务。如果直接颁发长期的令牌,客户端在登录后不再与授权服务器接触,此时张三的扣扣账号涉嫌及批量点赞/批量加好友/使用第三方客户端等业务违规操作被暂时冻结,需要前往扣扣自助处理或进行资金管理5,但是张三正在游玩卑微斗农民,并没有时间搭理。此时张三的账号已经处于异常状态,存放受保护资源的服务器无法得知,如果令牌是长期的,则会一直向客户端提供服务,这非常危险。因此客户端需要定时向授权服务器获取一次资源所有者的状态,以便增加安全性,这才是刷新令牌出现的真实原因,而不完全是用于防止被盗。

参考文献

https://dev.mi.com/console/doc/detail?pId=711

https://account.lolinya.net/docs/

https://datatracker.ietf.org/doc/html/rfc5849

https://datatracker.ietf.org/doc/html/rfc6749

https://datatracker.ietf.org/doc/html/rfc6750

https://datatracker.ietf.org/doc/html/draft-hammer-oauth-v2-mac-token-02

  1. 国内短视频平台:仅为本人对平台的称呼,未有任何诋毁与相关方面想法,请勿过度解读,仅为缩小平台范围,未有其他任何含义 ↩︎
  2. 张三:本人随意起的名字,如有雷同请自行使用开发者调试工具修改为其他名字,未有任何其他含义 ↩︎
  3. 扣扣:本人随意起的名字,并非深圳市腾讯计算机股份有限公司于1999年2月11日推出的多平台即时通信软件,如有雷同请自行使用开发者调试工具修改为其他名字,未有任何其他含义 ↩︎
  4. 卑微斗农民:本人随意起的应用程序名字,并非深圳市腾讯计算机股份有限公司旗下的游戏,此外,本人也不提倡棋牌类游戏,也不支持赌博,并且也无任何此方面的向导,仅为应用程序的示例,未有其他任何含义 ↩︎
  5. 涉及批量点赞/批量加好友/使用第三方客户端等业务违规操作被暂时冻结,需要前往扣扣自助处理或进行资金管理:本人随意想的理由,与其他任何应用都无关,仅为说明刷新令牌的重要性,如有雷同纯属巧合,无违规方面的向导,如有需要,请自行使用开发者调试工具修改为其他原因 ↩︎
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-2-13 2,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本概念
  • 授权流程
  • 基于 Nya Account 的应用
    • 创建应用
      • 获取授权码
        • 下发访问令牌
          • 请求受保护的资源示例
          • 对令牌相关知识的一些补充
          • 参考文献
          相关产品与服务
          多因子身份认证
          多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档