HTTP协议是一种无状态的协议。也就是第一次携带用户名和密码认证后。下一次访问HTTP协议不会携带认证的信息。这就需要传递认证信息。 传统的服务器识别客户端都是通过Session。当一个客户端连接到服务器之后,一般都会经过认证,会在服务器上创建出Session。当返回响应时,会将Session的标识一起返回给客户端。也就是SessionId。对于客户端来说就是Cookie。之后访问都会自动携带Cookie。但是会存在以下问题:
1、服务器保存所有的Session
,随着客户端增多,服务器开销会增大。
2、移动端,比如手机等没有Cookie
3、分布式系统不适用,Session是保存到特定的服务器上的
。比如Session保存在机器A,下次访问到机器B,但是机器B不存在Session。有特定的解决方法,就是Session共享。
4、Cookie是自动携带
的,会有CSRF
攻击的风险。
5、Cookie无法跨域
,对单点登录不适用。
如果认证成功后,将认证信息,比如一些随机字符串经过摘要或数字签名后发送给客户端,客户端保存这些信息,以后访问都携带,比如通过请求头或Cookie携带,服务器通过摘要或数字签名判断这些信息的有效性(不需要知道这些信息是什么)。这就是TOKEN了。简单来说,TOKEN就是一个字符串。TOKEN是保存在客户端上的,并且经过服务器认证成功后生成的。服务器会校验TOKEN的有效性,如果篡改了,会校验失败。同时还有很多好处:
1、支持跨域访问,要将TOKEN放在请求头中。
2、无状态。TOKEN不需要保存在服务器的Session中。
3、更适用CDN:可以通过内容分发网络请求服务端的所有资料
4、适用移动端
5、不需要考虑CSRF攻击
那么JWT又是什么呢?JWT是TOKEN是实现之一。JWT全称是JSON Web Token,是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于作为JSON对象在各方之间安全地传输信息。此信息是经过数字签名的,因此可以验证和信任。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。官网地址是:https://jwt.io/
JWT以其紧凑的形式由三部分
组成,三部分由点(.)分隔
:
-
Header(头部)
-
Payload(负载)
-
Signature(签名)
因此,JWT通常如下所示。
xxxxx.yyyyy.zzzzz
Header
Header通常由两部分组成:令牌的类型(JWT)
和所使用的签名算法
(如HMAC SHA256或RSA)。比如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,这个JSON被Base64Url编码(不是加密),以形成JWT的第一部分。
Payload
令牌的第二部分是有效负载,其中包含声明。声明是关于实体(通常是用户)和附加数据的声明。有三种类型声明:已注册、公有,私有。
-
注册声明:这些是一组预定义的声明,不是强制性的,但建议使用,以提供一组有用的、可互操作的声明。它们分别是:
iss(发布者)
sub(主题)
aud(用户)
exp(过期时间)
nbf(在此时间或日期之前不可用)
iat(发布时间)
jti(标识JWT的JWT ID) -
公开声明:这些声明可以由使用JWT的人随意定义。但为了避免冲突,它们应该在IANA JSON Web令牌注册表中定义,或者定义为包含抗冲突命名空间的URI。
-
私有声明:这些是为在同意使用它们的各方之间共享信息而创建的自定义声明,既不是注册声明也不是公开声明。比如:
{
"sub": "1234567890",
"name": "Helen",
"admin": true
}
然后对有效载荷进行Base64Url编码,以形成JSON Web令牌的第二部分。
注意:JWT经过加密,不要将敏感信息放到里面。
Signature
要创建签名部分,您必须获取编码的标头、编码的有效载荷、秘钥、标头中指定的算法,并对其进行签名。
例如,如果要使用HMAC SHA256算法,则将以以下方式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在发送过程中没有更改,在使用私钥签名的令牌的情况下,它还可以验证JWT的发送者是否就是它所说的那个人。
可以在jwt官网生成和校验jwt: