用户认证方案

308 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

HTTP协议

http是无状态的,那么问题来了, 无状态是什么意思? 

  • 协议对于事物处理没有记忆能力
  • 对同一个url请求没有上下文关系
  • 每次请求是独立的,相互的请求结果都是没有关系。

简单来说: 每一此请求独立,彼此没有任何关系,http协议接受发过来的url请求,完成相对应的工作,反馈信息,如同一个黑盒,对于外界的情况都不清楚,只能完成黑盒接收到的url,完成对应的工作。 Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议, 就是请求加响应, 但是随着发展需要管理每一个人的会话,区分每一个不同人,不同时间,甚至不同地点发过来的请求。因为Http是无状态的,所以要考虑方法,实现管理会话的功能

Cookie与session认证模式

我们先讨论Cookie和session分别是什么?

Cookie

Cookie 是服务器发送给客户端的用于验证某一会话信息的数据,cookie中有很多字段。不同网站Cookie中字段是不一样的,是由服务器端设置的。Cookie中常放入session_id 或者 token 用来验证会话的登录状态。 image.png 这里简单介绍一下一些字段意思:

  • Expires:Cookie 的过期时间,默认过期时间为用户关闭浏览器时。
  • HttpOnly:指示浏览器不要在除了 HTTP(或者 HTTPS)请求之外暴露 Cookie。通过 JavaScript 脚本无法访问到 Cookie,能有效防止 XSS 攻击
  • Secure:设置 Cookie 的 Secure 属性为 true 时,意味着 Cookie 通信只限于加密传输,指示浏览器仅仅在通过安全/加密连接才能使用 Cookie。也就是说 Cookie 只有在 HTTPS 协议下才能上传到服务器,而 HTTP 协议下是无法上传的。

Session

session是保存在服务器端的经过加密的存储特定用户会话所需的属性及配置信息的数据。当我们打开浏览器访问某网站时,session建立,只要浏览器不关闭(也有时间限制,可以自己设置超时时间),这个网站就可以记录用户的状态。

他们是如何完成认证的!

  • 客户端使用用户名,密码进行认证
  • 服务端验证用户名,密码,判断正确后会生成Session存储在数据库中,将对应的SessionID封装进cookie返回到客户端
  • 客户端发出请求,需要携带cookie,
  • 服务端通过cookie解码出携带的SessionID,通过ID查到Session进行鉴权,通过权限,返回对应的信息到客户端

image.png 优点:

  • 管理了会话。

缺点:

  • 扩展性不好,当你的网站部署在多台服务器上,那么Session就需要单独存储并共享。
  • 服务端需要存储Seesion,由于Seesion需要查找,当大量用户在线的话,就会占用大量服务器资源,导致服务器性能降低
  • 安全性不好,难以防范CSRF攻击(CSRF:当你访问A网站,然后又访问了危险网站,那么攻击者就会拿到你的cookie,利用cookie去恶意请求)
  • 跨域问题,Cookie 属于同源策略限制的内容之一。

Token认证模式

基于上诉的Session的会话管理方式多个缺点,那么服务端不再存储信息存储Session,那么token就诞生了! 过程如下:

  • 客户端使用用户名,密码进行登录发起请求
  • 服务端验证用户名,密码,生成token返回给客户端
  • 客户端保存token,当再次发起请求时候则需要头部携带token
  • 服务端通过解码token获取权限,返回给客户端对应的返回信息

image.png token的诞生基本解决了Session的问题所在。

JWT机制

JWT(JSON Web Token) 是由 RFC7519 定义的,是一个在双方之间安全的传达一组信息的 JSON 对象。

jwt组成

类似组成 image.png jwt用点(.)将字符串分成了三部分

  • Header(头部)
  • Payload(负载)
  • Signature(签名)

image.png

header(头部)

header 部分是一个 JSON 对象,用来描述 JWT 的元数据

{
  "typ": "JWT",   //  表示对象是一个 JWT
  "alg": "HS256"  //  表示使用哪种 Hash 算法来创建签名,这里是 HMAC-SHA256
}

例如加密算法等固定的数据

payload(负载)

payload 部分也是一个 JSON 对象,实际需要传递的数据被存放在这里。我们除了使用官方提供的七个字段之外,也可以使用自定义的私有字段。 官方七个字段

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

除了官方字段,你可以自定义字段。 温馨提示:jwt不是加密的,只是用base64编码,所以任何人都能读到信息。不要把私密信息放到这个部分

Signature(签名)

Signature 部分是对前两部分的签名,防止数据篡改。 首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。 HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) 算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

工作流程

  • 前端将自己的用户名和密码发送到后端的接口
  • 后端核对用户名和密码之后,将用户的一些信息作为 payload,生成 JWT
  • 后端将 JWT 作为登录成功的返回结果返回给前端。前端可以将其结果保存在 localStorage/sessionStorage 中,登出时删除 JWT 即可。(最好不要保存在 Cookie 中,用了 Cookie 就不能设置 HTTPonly,并且存在跨域问题)
  • 每一次请求都将 JWT 放在 HTTP 请求头中的 Authorization 位,这样相比放在 Cookie 中可以跨域。
  • 服务器解码 JWT,如果 token 有效,那么处理这个请求
  • 用户登出,在客户端删除 token 即可,与服务端无关

jwt特点

  1. JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
  2. JWT 不加密的情况下,不能将秘密数据写入 JWT。
  3. JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
  4. JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
  5. JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
  6. 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

相关教程: www.ruanyifeng.com/blog/2018/0… juejin.cn/post/684490…