JSON Web Token (JWT) 与 Token认证

一、前言

1) JWT是什么?

JWT是目前最流行的跨域认证解决方案。
JWT是一个定义一种紧凑的,自包含的并且提供防篡改机制的传递数据的方式的标准协议。

2) 基于token的认证与session认证的区别

1️⃣传统的session认证:

http协议是一无状态协议,所以如果用户向后台应用提供了用户名和密码来进行认证,下一次请求时,用户还是要带上用户名和密码进行用户认证。为了使后台应用能识别是哪个用户发出的请求,只能在后台服务器存储一份用户登陆信息,这份信息也会在响应前端请求时返回给浏览器(前端),前端将其保存为cookie,下次请求时前端发送给后端应用,后端应用就可以识别这个请求是来自哪个用户了,这就是传统的session认证。

2.1.1 session认证的不足:

①影响服务端的性能:每一个用户经过后端应用认证之后,后端应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着内存中存储的认证用户的增多,服务端的开销会明显增大。
②影响了应用的扩展性:由于sessions 存放在服务器内存中,伴随而来的是可扩展性问题。当我们想要增加服务器来解决负载问题时,session 里的关键性信息会限制我们的扩展。
③网站安全 - CSRF攻击:因为基于cookie来进行用户识别, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。(参见下文的CSRF解读)
④CORS (跨域资源共享):当我们扩展应用程序,让数据能够从不同设备上访问时,跨域资源的共享会是一个让人头疼的问题。在使用 Ajax 抓取另一个域的资源时(移动端访问我们的 API 服务器),可能会出现禁止请求的情况。
⑤移动端:在移动应用上 session认证难以实现。

2.1.2 CSRF解读

CSRF(Cross-site request forgery)跨站请求伪造。在用户并不知情的情况下,冒充用户发送请求,在当前已经登录的web网站上执行恶意操作,比如恶意发帖,修改密码等。

图解:
JSON Web Token (JWT) 与 Token认证_第1张图片

2️⃣基于token的认证:

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。在大多数使用Web API的互联网公司中,token 是多用户下处理认证的最佳方式。

2.2.1 认证流程

JSON Web Token (JWT) 与 Token认证_第2张图片
客户端使用用户名跟密码请求登录 =>
服务端收到请求,去验证用户名与密码 =>
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端 =>
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里 =>
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token =>
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

2.2.2 token认证的优势

①支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.
②无状态(也称:服务端可扩展性):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.这种概念解决了在服务端存储信息时的许多问题。没有 session 信息意味着你的程序可以根据需要去增减机器,而不用去担心用户是否登录和已经登录到了哪里。
③更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
④CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。

二、JWT的组成

JSON Web Token (JWT) 与 Token认证_第3张图片
JWT由3部分构成:
Header.Payload.Signature( Header - 头部 、Payload - 负载 、Signature - 签名.),中间用点"."分隔.

2.1 Header

jwt的头部承载两部分信息:

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

Header JSON示例:

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

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

2.2 Payload

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。其中JWT预定义了一些Claim,供选用。

iss (issuer):签发人
exp (expiration time):过期时间,必须大于签发时间
sub (subject):主题
aud (audience):接收jwt的一方
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):jwt的唯一身份标识,主要用来作为一次性token。

还可以在Payload中定义自定义字段

{
  "sub": "1234567890",
  "name": "linianhui"
}

注意:JWT默认是明文展示,任何人都可以读取到,所以此处不要放私密信息

然后将其进行base64加密,得到Jwt的第二部分:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Imxpbmlhbmh1aSJ9

2.3 Signature

这一部分是可选的,由于前面Header和Payload部分是明文的信息,所以这一部分的意义在于保障信息不被篡改用的,生成这部分的方式如下:

var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var secret = '私钥';//也叫盐
var signature = HMACSHA256(encodedString, secret);

使用header中指定的签名算法对“header.payload”部分进行签名,得到的第3部分: hnOfZb95jFwQsYj3qlgFbUu1rKpfTE6AzgXZidEGGTk,然后组合成一个完整的JWT字符串 .

注意:secret是保存在服务器端的,JWT的签发生成也是在服务器端的,secret就是用来进行JWT的签发和JWT的验证,所以,它就是服务端的私钥,谨慎保护。因为签名的密钥是只有服务端才知道,所以可以保证这部分信息不被篡改。

三、如何使用JWT?

客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。

此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header的Authorization字段中。

Authorization: 'Bearer ' + token

当跨域时,也可以将JWT被放置于POST请求的数据主体中。

四、JWT的特点以及应用方向

①JWT不仅可用于认证,还可用于信息交换,理使用JWT有助于减少服务器请求数据库的次数。
②为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。

你可能感兴趣的:(授权认证,前端,json,javascript)