跳至主要內容

授权方案(php实现)

Mr.Lexon大约 6 分钟back-end

授权方案(php实现)

以下方案为用户登录授权参考

1. 采用数据库授权

本方法仅仅只在laravel实验过

思路

首先在用户表添加一列为token列,然后在登录校验成功之后,生成token,将其添加至数据库,并在登录成功之后返回token和用户id,在用户需要登出时,清空token列数据,在这个的基础上增加一个定时器,检查用户表的更新时间,当用户表的更新时间超过规定时间时,自动清空token列内容。

特征

  1. 缺陷明显: 首先此方法无法使用在大量用户场景,因这样会产生大量的sql操作,极大降低服务器性能
  2. 存在错误: 当用户表修改频繁时,会直接延长有效时间 总结这个方法既繁琐又低效。

2. 采用redis实现授权(基本)

思路

首先生成完token之后使用redis的键值模式存储token,键名建议写成如下格式:

[project_name]:user:[user_id]

然后使用对应的redis工具类存储,当他需要登出时结合用户id和token做一次校验,然后使用对应的redis删除即可,redis是有对应的方法设置过期时间。redis工具类实现见[[redis工具封装(基于laravel)]]

特征

  1. 省事
  2. 明码传输用户信息(?这个的描述有点问题) 这个方法只适合单纯的用户登录状态校验,并不对用户信息做存储,所以获取用户信息,只能通过再请求而无法通过其他方法获取。
  3. 可存储的信息较短 因为它在存储的过程中只能存储token所以要查看用户信息时是需要查询数据库。
  4. 若出现集群,需要将所有的服务端连入同一个redis

补充: 这个方法其实就是是Session ID,目标就是利用这个ID进行业务交互。

3.基于JWT形式的授权

JWT概念

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。

{
	"name": "张三",
	"role": "管理员",
	"expiraTime": "2022-11-9 00:00:00" 
}

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。 服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

整体结构:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vMTkyLjE2OC4xLjEyMjo4MDgwL2FwaS9hdXRoL2xvZ2luIiwiaWF0IjoxNzAxMDY4NTAzLCJleHAiOjE3MDEwNzIxMDMsIm5iZiI6MTcwMTA2ODUwMywianRpIjoiQkZYTFViS1NQaTFVdExHQSIsInN1YiI6IjEwIiwicHJ2IjoiMjNiZDVjODk0OWY2MDBhZGIzOWU3MDFjNDAwODcyZGI3YTU5NzZmNyJ9.TbrCXIYMCTowWfpvz1EetTwRquANfmufsIm4uMiRA84
红色的为`header`(头) 紫色的为`payload` (所携带传输内容) 青色的为`signature` (签名)

标头通常由两部分组成:令牌的类型(JWT)和正在使用的签名算法,例如 HMAC SHA256 或 RSA。 例如:

{
  "alg": "HS256",
  "typ": "JWT"
}

然后通过Base64URL编码,得出第一部分

payload

令牌的第二部分是payload,其中包含claimsclaims是关于实体(通常是用户)和其他数据的语句。claims分为三种类型:注册claims、公共claims和私人claims

  1. 已注册claims:这些是一组预定义的claims,这些claims不是强制性的,但建议提供一组有用的、可互操作的claims。其中一些是:iss(发行人)、exp(到期时间)、sub(主题)、aud(受众)等。
  2. 公共claims:这些claims可以由使用 JWT 的人随意定义。但为了避免冲突,应在 IANA JSON Web 令牌注册表中定义它们,或将其定义为包含防冲突命名空间的 URI。
  3. 专用claims:这些是自定义claims,用于在同意使用它们的各方之间共享信息,既不是注册claims,也不是公开claims。 一般是传输用户非敏感信息所使用的 例:
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后通过Base64URL编码,得出第二部分

signature

要创建signature部分,您必须获取编码的标头、编码的payloadsecretheader中指定的算法,并对其进行签名。 例如,如果要使用 HMAC SHA256 算法,则将按以下方式创建签名:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

这里的secret是你自己生成出来的,这个整体用于验证消息在此过程中没有更改,对于使用私钥签名的令牌,它还可以验证 JWT 的发送者是否是他本人。

特征

  1. 不安全 因为信息是直接储存在payload里面的,而且还是无状态的,所以只能等jwt自己过期了才可以删除,一旦泄露就可以使用其获取用户信息
  2. 可扩展 因为是直接携带JSON返回,所以可以直接拓展返回信息
  3. 降低数据库的使用 因为其本身的特性,所以可以交换信息,降低服务器查询数据库的次数 具体实现见:JWT实现open in new window 但是这个方案较老,不适宜再使用

4. OAuth2登录认证

OAuth概念

OAuth 2.0是一个业界标准的授权协议,其定义了四种可以适用于各种应用场景的授权交互模式:授权码模式、应用授信模式、用户授信模式、简化模式。其中,授权码模式被广泛应用于第三方互联网开放平台,通过第三方登录是其最常见应用场景之一,比如使用微信、QQ和淘宝账号进行登录。 通俗点说就是当有第三方应用需要授权你服务器的用户信息时,可以通过这个方式进行授权。 参与该模式的有四个角色:

  1. 第三方应用
  2. 授权服务器
  3. 资源服务器
  4. 用户

流程:

首先第三方应用请求认证服务器获取token,然后认证服务器询问用户是否同意授权,当用户同意授权时,认证服务器将token发送至第三方应用,然后第三方应用通过token请求资源服务器。 在这里,第三方应用可以转换成为客户端,然后授权和资源服务器为同一服务端,授权服务器负责token的续期以及请求客户端的管理。 如果这是第一次授权则请求对应的客户端密钥进行存储,以证明用户已授权过,下一次授权就可以使用客户端密钥进行授权。

特征:

  1. 因为token本身也是由JWT生成的,所以在token本身继承了所有JWT里的token的特点。
  2. 相较于JWT来说要安全些,因为做了两次授权
  3. 用户能够选择哪些资源可以被访问,而不必共享他们的密码。
  4. OAuth2相较于JWT来说要复杂些 具体实现:laravel passportopen in new window

dawd

上次编辑于:
贡献者: Lexon