阅读 342

前后端分离常用的认证方式( Session 、JWT)

HTTP 是无状态的,所以无法分辨是谁发起的请求。
前后端分离中前后端的交互是通过 API 进行的,那么其中的认证是少不了的。前后端分离中常用的认证方式有下面几种:

  • Session-Cookie 验证
  • Token 验证
  • OAuth(开放授权)

一、Session-Cookie 机制 (web应用中最常见的)

当服务端需要对访问的客户端进行身份认证时,常用的做法是通过session-cookie 机制;

session-cookie 工作流程:

不了解session 和cookie 的建议先去看这个文章:对session和cookie的认识

sequenceDiagram
客户端->>服务端: 将用户名密码发到服务器认证
服务端->>服务端: 服务端通过认证后,会缓存该会话(session),生成sessionID
服务端-->>客户端: 服务端set-cookie 设置cookie: sessionID = XX, 返回sessionID给客户端
客户端-)服务端: 浏览器会自动将服务器设置的Cookie附加在HTTP请求的头字段Cookie中。
服务端->>服务端: 服务端验证session, 服务端根据sessionID去查对应用户信息
服务端->> 客户端:如果有则直接将处理结果返回

Session-Cookie 认证存在的问题:

  • 当客户访问量增加,服务端需要存储大量的session会话,对服务端有很大考验
  • 当服务端为集群时,用户登录其中一台服务器,会将session保存在该服务器的内存中, 但是当用户访问其他服务器时。会无法访问。(已经有了成熟的解决方案)
    • 可以采用使用缓存服务器来保证共享
    • 第三方缓存来保存session
  • 由于依赖cookie,所以存在CSRF安全问题

二、Token 认证机制:

token(令牌,访问资源的凭证) 认证是一种机制,具体的实现可以是一个随机的字符串,也可以是标准的jwt。

token需要查库验证token 是否有效,而JWT不用查库或者少查库,直接在服务端进行校验。

因为用户的信息及加密信息在第二部分payload和第三部分签证中已经生成,只要在服务端进行校验就行,并且校验也是JWT自己实现的。

这里主要说下jwt的实现。

具体实现JWT的相关介绍

JWT 是什么 ?

JWT 是 JSON Web Token的缩写.
是由3部分拼成的一个字符串,每个部分之间用.分隔。
在HTTP通信 过程中,进行身份认证的一种方式。也可以在各个服务之间进行信息传输
是Token认证方式的一种具体实现

JWT的认证流程:

jwt的认证方式,服务端不需要保存任何session会话,是无状态的,比较容易扩展。
因为不依赖cookie,可以存在localStorage里,所以可以防御csrf攻击,更安全。
JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

sequenceDiagram
客户端->>服务端: 将用户名密码发到服务器认证
服务端->>服务端: 服务端通过认证后,签发token
服务端-->>客户端: 返回token给客户端
客户端-->>客户端: 存在loacalStorage 或者cookie里
客户端-)服务端: 请求时 将token放在请求头header或者参数里
服务端->>服务端: 服务端验证token
服务端->> 客户端: 返回用户请求的资源信息

放在cookie里会引起跨域,如何避免?

  • 放在HTTP请求的头信息Authorization字段里。Authorization: Bearer <token>.
  • 另一种做法是,跨域的时候,token(jwt) 就放在 POST 请求的数据体里面。
config.headers.common['Authorization'] = `Bearer ${access_token || ''}`;
或者 axios.defaults.headers.common["token"] = this.token;
复制代码

JWT 的数据结构 ?

JWT 默认是不加密的,所以不要把秘密信息放在这里。

  • Header(头部): JSON,使用 Base64 URL 转成字符串,描述元数据
  • Payload (负载): JSON,使用 Base64 URL 转成字符串,实际需要传递的数据
    • JWT规定的7个官方字段:
      • iss (issuer):签发人
      • exp (expiration time):过期时间
      • sub (subject):主题
      • aud (audience):受众
      • nbf (Not Before):生效时间
      • iat (Issued At):签发时间
      • jti (JWT ID):编号
    • 还可以定义私有字段:
  • Signature(签名): 对前面2部分的签名,防止数据篡改
    • 首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户
    • 使用 Header 里面指定的签名算法,按照下面的公式产生签名。

产生的签名

HMACSHA256(
 base64UrlEncode(header) + "." +
 base64UrlEncode(payload),
 secret)
复制代码

Header 的JSON 对象

{
 "alg": "HS256", // 表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256)
 "typ": "JWT" // 表示令牌(token)的类型
}
复制代码

大概的结果

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE0MTY3OTc0MTksImV4cCI6MTQ0ODMzMzQxOSwiYXVkIjoid3d3Lmd1c2liaS5jb20iLCJzdWIiOiIwMTIzNDU2Nzg5Iiwibmlja25hbWUiOiJnb29kc3BlZWQiLCJ1c2VybmFtZSI6Imdvb2RzcGVlZCIsInNjb3BlcyI6WyJhZG1pbiIsInVzZXIiXX0.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

复制代码

JWT 安全性问题

  • JWT 是明文编码: JWT 的编码是明文 Base64 的一个编码,是可以反编译的。在使用 JWT 传输信息的时候,不要放置重要敏感信息,最好使用 https。

JWT 泄露问题:

解决 JWT 的泄露问题是一个平衡的问题。有三种处理方式由轻到重,看你业务重要性酌情选择:

  • 将 JWT 的过期时间设置的很短,即使泄露也无关紧要。或者旧的直接加入黑名单
  • 在服务端设计 JWT 的黑名单机制,将泄露的 Token 加黑名单即可。
  • 保存签发的 JWT,当 JWT 泄露时,直接设置失效。

JWT 的优点

  • 轻量级:JWT是非常轻量级的,传输的方式多样化,可以通过URL/POST参数/HTTP头部等方式传输。(一般放在 x-access-token里)
  • 无状态/跨域认证:令牌包含所有用于标识用户的信息,这消除了对会话状态的需要。 如果我们使用负载平衡器,我们可以将用户传递给任何服务器,而不是绑定到我们登录的同一台服务器上。
  • 可重用性/扩展性:我们可以有许多独立的服务器在多个平台和域上运行,并重复使用相同的令牌来验证用户。 构建与另一个应用程序共享权限的应用程序很容易。
  • 安全性:无需担心跨站请求伪造(CSRF)攻击。

JWT 的缺点

JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑

使用场景

  • 利用token 可以防止表单重复提交(主要说的是后端限制)
    • 前端可以通过按钮置灰防止表单提交
    • 后端的话就是验证request里的token 是否和session里的token相等,从而判断这个表单是否提交过
  • 用户身份验证(授权):这是最常见的使用场景,解决单点登录问题。因为JWT使用起来轻便,开销小,服务端不用记录用户状态信息(无状态),所以使用比较广泛;
  • 信息交换:JWT是在各个服务之间安全传输信息的好方法。因为JWT可以签名,例如,使用公钥/私钥对儿 - 可以确定请求方是合法的。此外,由于使用标头和有效负载计算签名,还可以验证内容是否未被篡改。

三、OAuth 认证:

OAuth(Open Authorization)是一个开放标准,允许用户授权第三方网站访问他们存储在服务端的用户信息。
我们常见的的 QQ、微信等第三方登录便是 Auth 认证方式。

  • OAuth 协议有 1.0 和 2.0(目前最主要的用户身份验证和授权方式) 两个版本。
    • 相比较 1.0 版,2.0 版整个授权验证流程更简单更安全,

OAuth 更像是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

在单纯的前后端分离系统中,OAuth 并不是常用的方式,它更多的应用在不同系统之间的授权交互。

四、session-cookie机制 和token机制的对比:

首先,当前后端分离时我们会因为同源策略而无法设置cookie和sessionid。当然了我们有很多方式去解决这个问题,比如反向代理和jsonp等。但这仍然不如直接使用jwt来的简便。其次就是要说到jwt与传统的身份认证相比有什么优势了。

session-cookie 机制jwt认证机制
跨域cookie 不允许跨域访问可以跨域认证
安全性依赖cookie,容易被CSRF不依赖cookie 更安全
扩展性ios等原生平台没有cookie扩展性更好
数据存储数据存在服务端数据存在jwt里
性能服务端需要保存session,大量查询时性能较差HMACSHA256计算

五、总结:

session-cookie方案 就是利用cookie来管理session,即把 Session 放入 HTTP 响应中还给客户端,并保存在客户端,当客户端发送下一次请求的时候,就把这个 Session 一起发送回来,这样就能这次的请求是谁发出来的了。

而 Token 方案 也就是JWT 相对来说 不依赖cookie,更安全,原生平台也可以用,各个系统之间也可以,允许跨域认证,扩展性更好。而jwt为了防止泄露,应该将有效期设置的比较短,为了减少盗用, 最好使用HTTPS协议传输,因为HTTP是明码传输的

个人觉得 token认证和session认证 需要根据自己的业务去选择,虽然session认证有缺点, 但是现在其实已经有比较成熟的解决方案了。相对来说的话,token的扩展性和安全性都更好一些

六、参考

  1. Cookie/Session 的机制与安全
  2. token解决前后端分离认证和跨域问题和JWT的使用 代码实现
  3. 前后端分离常用的认证方式
文章分类
前端
文章标签