前后端鉴权方法二
10种常用前后端鉴权方法,让你不再迷惘(下)
6. OAuth 2.0
在我们实际浏览网站的时候,当我们登录的时候除了输入当前网站的账号密码外,我们还发现可以通过第三方的 QQ 或者 微信登录,那么这又是如何做到了呢,这就要谈到 OAuth 了。
OAuth 协议又有 1.0 和 2.0 两个版本,2.0 版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。
6.1 什么是 OAuth 2.0?
OAuth 是一个开放标准,允许用户授权第三方网站 (CSDN、思否等) 访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站;
常见的提供 OAuth 认证服务的厂商: 支付宝、QQ、微信、微博
简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(Token),用来代替密码,供第三方应用使用。
令牌与密码的差异:
令牌(Token)
与 密码(Password)
的作用是一样的,都可以进入系统,但是有三点差异。
- 令牌是短期的,到期会自动失效: 用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。
- 令牌可以被数据所有者撤销,会立即失效。
- 令牌有权限范围(scope): 对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。
OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成四种授权模式 (Authorization Grant) ,适用于不同的互联网场景。
无论哪个模式都拥有三个必要角色:客户端
、授权服务器
、资源服务器
,有的还有用户(资源拥有者)
,下面简单介绍下四种授权模式。
6.2 授权码模式
授权码(Authorization Code Grant)
方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
这种方式是最常用的流程,安全性也最高,它适用于那些有后端服务的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
一句话概括:客户端换取授权码,客户端使用授权码换token,客户端使用token访问资源
授权码模式的步骤详解
- 客户端:打开网站 A,点击登录按钮,请求 A 服务,A 服务重定向 (重定向地址如下) 至授权服务器 (如QQ、微信授权服务)。
1
2
3
4
5
https:
//qq.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
上面 URL 中,
response_type
参数表示要求返回授权码(code
),client_id
参数让 B 知道是谁在请求,redirect_uri
参数是 B 接受或拒绝请求后的跳转网址,scope
参数表示要求的授权范围(这里是只读)
- 授权服务器:
授权服务网站
会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时授权服务网站
就会跳回redirect_uri
参数指定的网址。跳转时,会传回一个授权码,就像下面这样。
1
https:
//a.com/callback?code=AUTHORIZATION_CODE
上面 URL 中,
code
参数就是授权码。
- 网站 A 服务器:拿到授权码以后,就可以向
授权服务器 (qq.com)
请求令牌,请求地址如下:
1
2
3
4
5
6
https:
//qq.com/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL
上面 URL 中,
client_id
参数和client_secret
参数用来让授权服务器 确认 A 的身份(client_secret
参数是保密的,因此只能在后端发请求),grant_type
参数的值是AUTHORIZATION_CODE
,表示采用的授权方式是授权码,code
参数是上一步拿到的授权码,redirect_uri
参数是令牌颁发后的回调网址。
- 授权服务器:收到请求以后,验证通过,就会颁发令牌。具体做法是向
redirect_uri
指定的网址,发送一段 JSON 数据。
1
2
3
4
5
6
7
8
9
{
"access_token"
:
"ACCESS_TOKEN"
,
"token_type"
:
"bearer"
,
"expires_in"
:2592000,
"refresh_token"
:
"REFRESH_TOKEN"
,
"scope"
:
"read"
,
"uid"
:100101,
"info"
:{...}
}
上面 JSON 数据中,
access_token
字段就是令牌,A 网站在后端拿到了,然后返回给客户端即可。
6.3 隐藏式模式(Implicit Grant)
有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。OAuth2.0 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)”隐藏式”(implicit)。
一句话概括:客户端让用户登录授权服务器换token,客户端使用token访问资源
。
隐藏式模式的步骤详解
- 客户端:打开网站 A,A 网站提供一个链接,要求用户跳转到
授权服务器
,授权用户数据给 A 网站使用。如下链接:
1
2
3
4
5
https:
//qq.com/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
上面 URL 中,
response_type
参数为token
,表示要求直接返回令牌。 - 授权服务器:用户跳转到授权服务器,登录后同意给予 A 网站授权。这时,授权服务器就会跳回
redirect_uri
参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。
1
https:
//a.com/callback#token=ACCESS_TOKEN
上面 URL 中,
token
参数就是令牌,A 网站因此直接在前端拿到令牌。
注意:
- 令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在”中间人攻击”的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。
- 这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。
6.4 用户名密码式模式(Password Credentials Grant)
如果你高度信任某个应用,OAuth 2.0 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为”密码式”(password)。
一句话概括:用户在客户端提交账号密码换token,客户端使用token访问资源。
密码式模式的步骤详解
- 客户端:A 网站要求用户提供
授权服务器(qq.com)
的用户名和密码。拿到以后,A 就直接向授权服务器
请求令牌。
1
2
3
4
5
https:
//oauth.b.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID
上面 URL 中,
grant_type
参数是授权方式,这里的password
表示”密码式”,username
和password
是授权服务器
的用户名和密码。 - 授权服务器:
授权服务器
验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 网站因此拿到令牌。
这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。
6.5 客户端模式(Client Credentials Grant)
客户端模式指客户端以自己的名义,而不是以用户的名义,向授权服务器
进行认证。
主要适用于没有前端的命令行应用。
一句话概括:客户端使用自己的标识换token,客户端使用token访问资源
。
客户端模式的步骤详解
- 客户端:客户端向
授权服务器
进行身份认证,并要求一个访问令牌。请求链接地址:
1
2
3
4
https:
//oauth.b.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
上面 URL 中,
grant_type
参数等于client_credentials
表示采用凭证式,client_id
和client_secret
用来让授权服务器
确认 A 的身份。 - 授权服务器:
授权服务器
验证通过以后,直接返回令牌。
注意:这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。
6.5 授权模式选型
按授权需要的多端情况:
模式 | 需要前端 | 需要后端 | 需要用户响应 | 需要客户端密钥 |
---|---|---|---|---|
授权码模式 Authorization Code | ✅ | ✅ | ✅ | ✅ |
隐式授权模式 Implicit Grant | ✅ | ❌ | ✅ | ❌ |
密码授权模式 Password Grant | ✅ | ✅ | ✅ | ✅ |
客户端授权模式 Client Credentials | ❌ | ✅ | ❌ | ✅ |
按照客户端类型与访问令牌所有者分类:
上述主要比较浅显的讲解了 OAuth2.0 的基本逻辑,如若想详细深入的了解,可查看官方文档 OAuth 或 RFC 6749; 亦可查看 OAuth 2.0 概念及授权流程梳理 做对比
前后端鉴权方法二
7. 联合登录和信任登录
7.1 什么是联合登陆
联合登录
指同时包含多种凭证校验的登录服务,同时,也可以理解为使用第三方凭证进行校验的登录服务。
通俗点讲: 对于两个网站 A 和 B,在登录 A 网站的时候用 B 网站的帐号密码,就是联合登录,或者登录 B 网站的时候使用 A 网站的帐号密码,也是联合登录。
这样的概念其实与上面所讲的 OAuth2.0 的 用户名密码式模式
认证方式类似。
最经典的莫过于 APP 内嵌 H5 的使用场景,当用户从 APP 进入内嵌的 H5 时,我们希望 APP 内已登录的用户能够访问到 H5 内受限的资源,而未登录的用户则需要登录后访问。
这里思路主要有两种,一种是原生跳转内嵌 H5 页面时,将登录态 Token 附加在 URL 参数上,另一种则是内嵌 H5 主动通过与原生客户端制定的协议获取应用内的登录状态。
7.2 什么是信任登录
信任登录
是指所有不需要用户主动参与的登录,例如建立在私有设备与用户之间的绑定关系,凭证就是私有设备的信息,此时不需要用户再提供额外的凭证。信任登录又指用第三方比较成熟的用户库来校验凭证,并登录当前访问的网站。
通俗点讲: 在 A 网站有登录状态的时候,可以直接跳转到 B 网站而不用登录,就是 信任登录
。
目前比较常见的第三方信任登录帐号如:QQ 号淘宝帐号、支付宝帐号、微博帐号等。
我们不难发现 OAtuth 2.0 其实就是信任登录的缩影,因为正是有了 OAuth,我们的信任登录才得以实现。
前后端鉴权方法二
8. 唯一登录
— 假设现在产品经理提一个需求:我想要实现用户只能在一个设备上登录,禁止用户重复登录;
— 身为优秀的程序员的我们当然是满足他啦 !!
8.1 什么是唯一登录
唯一登录,指的是禁止多人同时登录同一账号,后者的登录行为,会导致前者掉线。
通俗点讲就是:A 账号在 A 电脑上登录后,A 账号此时又用 B 电脑再次登录,则 A 电脑请求页面时,提示“重新登录”的信息,并跳转到登录页面
8.3 唯一登录步骤详解
用户在客户端 A 操作:
- 输入账号请求登录接口;
- 后端生成对应 Token 并且返回给客户端 A,并且在服务端保存一个登录状态;
- 客户端A 保存 Token,并且每次请求都在 header 头中携带对应的 Token;
用户在客户端 B 操作:
突然用户在客户端 B 上开始登录操作,我们会发现,步骤和在客户端A上面的操作几乎是一致的;
只是后端在生成新的 Token 时,要先验证登录状态,然后再生成对应新的 Token;
前后端鉴权方法二
9. 扫码登录
9.1 什么是扫码登录
扫码登录通常见于移动端 APP 中,很多 PC 端的网站都提供了扫码登录的功能,无需在网页上输入任何账号和密码,只需要让移动端 APP (如微信、淘宝、QQ等等) 中已登录用户主动扫描 二维码
,再确认登录,以使 PC 端的同款应用得以快速登录的方式就是 扫码登录
。
9.2 什么是二维码
二维码
又称二维条码,常见的二维码为 QR Code,QR 全称 Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。
通过上面所述,我们不难发现,扫码登录需要三端 (PC端
、手机端
、服务端
) 来进行配合才能达到登录成功的效果;
9.4 扫码登录的步骤详解 (待扫码阶段、待确认阶段、已确认阶段)
待扫码阶段:
- PC端:打开某个网站 (如taobao.com) 或者某个 APP (如微信) 的扫码登录入口;就会携带 PC 端的设备信息向服务端发送一个获取二维码的请求;
- 服务端:服务器收到请求后,随机生成一个 UUID 作为二维码 ID,并将 UUID 与
PC 端的设备信息
关联起来存储在 Redis 服务器中,然后返回给 PC 端;同时设置一个过期时间,在过期后,用户登录二维码需要进行刷新重新获取。 - PC 端:收到二维码 ID 之后,将二维码 ID 以
二维码的形式
展示,等待移动端扫码。并且此时的 PC 端开始轮询查询二维码状态,直到登录成功。如果移动端未扫描,那么一段时间后二维码会自动失效。
已扫码待确认阶段:
- 手机端:打开手机端对应已登录的 APP (微信或淘宝等),开始扫描识别 PC 端展示的二维码;移动端扫描二维码后,会自动获取到二维码 ID,并将移动端登录的信息凭证(Token)和二维码 ID 作为参数发送给服务端,此时手机必须是已登录(使用扫描登录的前提是移动端的应用为已登录状态,这样才可以共享登录态)。
- 服务端:收到手机端发来的请求后,会将
Token 与二维码 ID
关联,为什么需要关联呢?因为,当我们在使用微信时,移动端退出时,PC 端也应该随之退出登录,这个关联就起到这个作用。然后会生成一个临时 Token,这个 Token 会返回给移动端,一次性 Token 用作确认时的凭证。
已确认阶段:
- 手机端:收到确认信息后,点击确认按钮,移动端携带上一步中获取的
临时 Token
发送给服务端校验; - 服务端:服务端校验完成后,会更新二维码状态,并且给 PC 端生成一个
正式的 Token
,后续 PC 端就是持有这个 Token 访问服务端。 - PC端:轮询到二维码状态为已登录状态,并且会获取到了生成的 Token,完成登录,后续访问都基于 Token 完成。
前后端鉴权方法二
10. 一键登录(适用于原生APP)
10.1 账号密码登录
大家都知道,最传统的登录方式就是使用账号加密码登录,简单粗暴,一般也不会出现什么问题;
缺点:
- 但这种方式要求用户要记住自己的账号和密码,也就是有一个记忆成本。用户为了降低记忆成本,很可能会在不同平台使用同一套账号密码。从安全角度考虑,一旦某个平台的账号密码泄露了,会连累到该用户使用的其他平台。
- 另外,由于账号和个人身份无关,意味着同一个用户可以注册多个不同的账号,也就是可能会有恶意注册的情况发生。
直到手机卡的强制实名制才得以解决!
10.2 手机号验证码登录
随着无线互联的发展以及手机卡实名制的推广,手机号俨然已成为特别的身份证明,与账号密码相比,手机号可以更好地验证用户的身份,防止恶意注册。
但是手机号注册还是需要一系列繁琐的操作:输入手机号、等待短信验证码、输入验证码、点击登录。整个流程少说二十秒,而且如果收不到短信,也就登录补了,这类问题有可能导致潜在的用户流失。
从安全角度考虑,还存在验证码泄漏的风险。如果有人知道了你的手机号,并且窃取到了验证码,那他也能登录你的账号了。
所以就有了一键登录操作!
10.3 什么是一键登录
我们想一下,为什么我们需要验证码?验证码的作用就是确定这个手机号是你的,那除了使用短信,是否还有别的方式对手机号进行认证?
于是,就有了咱们的主角一键登录。
短信验证码的作用就是证明当前操作页面的用户与输入手机号的用户为相同的人,那么实际上只要我们能够获取到当前手机使用的手机卡号,直接使用这个号码进行登录,不需要额外的操作,这就是一键登录。
一键登录能不能做,取决于运营商是否开放相关服务;随着运营商开放了相关的服务,我们现在已经能够接入运营商提供的 SDK 并付费使用相关的服务。
一键登录步骤详解:
- SDK 初始化: 调用 SDK 方法,传入平台配置的 AppKey 和 AppSecret
- 唤起授权页: 调用 SDK 唤起授权接口,SDK 会先向运营商发起获取手机号掩码的请求,请求成功后跳到授权页。授权页会显示手机号掩码以及运营商协议给用户确认。
- 同意授权并登录: 用户同意相关协议,点击授权页面的登录按钮,SDK 会请求本次取号的 Token,请求成功后将 Token 返回给客户端
- 取号: 将获取到的 Token 发送到自己的服务器,由服务端携带 Token 调用运营商一键登录的接口,调用成功就返回手机号码。服务端用手机号进行登录或注册操作,返回操作结果给客户端,完成一键登录。
注意:
在认证过程中,需要用户打开蜂窝网络,如果手机设备没有插入 SIM 卡、或者关闭蜂窝网络的情况下,是无法完成认证的。所以就算接入一键登录,还是要兼容传统的登录方式,允许用户在失败的情况下,仍能正常完成登录流程。
参考链接:【总结分享】10种常用前后端鉴权方法,让你不再迷惘-头条-PHP中文网
友情链接:https://www.ccwisdom.com/industrynews/