1.JWT即JSON Web Tokens,他可以用来安全的传递信息,因为这些信息是经过数字签名的
2.JWT可以使用一种加密算法比如HMAC 算法,也可以使用公钥/私钥的非对称算法
3.因为JWT签名后的信息够短,可以放在url里、request body里、http header里,传输够快。
4.荷载信息里包含所有你想要的,避免不止一次的去查询数据库
5.JWT的使用场景主要包括:
1) 认证,这是比较常见的使用场景,只要用户登录过一次系统,之后的请求都会包含签名出来的token,通过token也可以用来实现单点登录。
2)交换信息,通过使用密钥对来安全的传送信息,可以知道发送者是谁、放置消息被篡改。
6.JSON Web Tokens由三部分组成,用英文句点分割(.) ,一般看起来例如:xxxxx.yyyyy.zzzzz
分为:
- Header 头信息
- Payload 荷载信息,实际数据
- Signature 由头信息+荷载信息+密钥 组合之后进行加密得到
1) Header 头信息通常包含两部分,type:代表token的类型,这里使用的是JWT类型。 alg:使用的Hash算法,例如HMAC SHA256或RSA.
{
"alg": "HS256",
"typ": "JWT"
}
// 这会被经过base64Url编码形成第一部分
2)Payload 一个token的第二个部分是荷载信息,它包含一些声明Claim(实体的描述,通常是一个User信息,还包括一些其他的元数据)
声明分三类:
1)Reserved Claims,这是一套预定义的声明,并不是必须的,这是一套易于使用、操作性强的声明。包括:iss(issuer)、exp(expiration time)、sub(subject)、aud(audience)等
2)Plubic Claims,
3)Private Claims,交换信息的双方自定义的声明
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
// 同样经过Base64Url编码后形成第二部分
3) signature 使用header中指定的算法将编码后的header、编码后的payload、一个secret进行加密
例如使用的是HMAC SHA256算法,大致流程类似于: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
这个signature字段被用来确认JWT信息的发送者是谁,并保证信息没有被修改
7.这个JSON Web Tokens包含了必要的用户信息,减少了对数据库进行多次查询的需要。
8.由于没有使用Cookies,Cross-Origin Resource Sharing (CORS) ,跨域的资源访问不会成为问题。
JWT官网有一张图描述了JWT的认证过程:
9.JWT、JWS、JWE的区别(转自https://securedb.co/community/jwt-vs-jws-vs-jwe/)
1)JWT(JSON Web Tokens),jwt长度较小,且可以使用URL传输(URL safe)。不想cookies只能在web环境起作用。 JWT可以同时使用在web环境和RESTfull的接口。
2)对于开发者来说,JWT与另外两种相近的标准:JWS(JSON Web Signature)、JWE(JSON Web Encryption),容易引起混乱。
3)关于JWT的描述,可以参考RFC7519(https://tools.ietf.org/html/rfc7519)的描述:
JSON Web Token (JWT) 是一个间接地、URL安全的,表现为一组声明,可以在双方之间进行传输。一个JWT的声明,是指经过编码后的一个JSON对象,这个JSON对象可以是一个JSON Web Signature(JWS)结构的荷载(payload),或者是一个JSON Web Encryption(JWE)结构的明文。允许使用声明进行数字签名,或者通过一个Message Authentication Code(MAC)进行完整性保护可选择是否加密。
简单来说,JWTs表现为一组被编码为JWS and/or JWE结构的JSON object的声明(Claim).
换言之,一组JWT声明(就是表现为JSON格式的Claims)被通过JWS结构或者JWE结构(或者同时使用两种)发送,决定于你如何去实现它。所以,当你发送JWT给别人是,它实际上是一个JWT荷载或者JWE荷载。JWS荷载更加常用。
关于声明(Claim),他们是关于用户的简单断言(assertion)。比如,对于一个用户在工资系统中进行认证,这组Claims可能看起来像这样:
{ "userId":"johndoe", "role":"employee", "pay-frequency":"biweekly" }
现在,将它嵌入一个JWS结构,整个字符串看起来像是这样:
{
"alg":"HS256"
} // End of JOSE Header
.
{
"userId": "johndoe",
"role": "employee",
"pay-frequency": "biweekly"
} // End of JWT Claims
.
{
} // End of Signature in case of JWS
4)关于JWS
顾名思义,JWS模式对这个内容进行了数字化签名。这个内容被用来存放JWT的声明.服务端签名出JWT并且发送到客户端,并在用户成功认证后进行应答。服务器期望客户端在下次请求的时候将JWS作为请求的一部分,发送回服务端。
如果我们处理的客户端是欺骗者则么办?这就是签名(signature)需要出场的地方了。签名携带了完整的可验证的信息。换句话说,服务器可以确认,接收到的JWT声明里的JWS是没有经过欺骗客户端、中间者进行修改的。
服务端通过验证消息的签名来确保客户端没有修改声明。如果服务端检测到任何修改,可以采取适当的动作(拒绝这次请求或者锁定客户端之类的)
客户端同样可以验证签名,为了做到这点,客户端也需要服务端的secret(密钥)(如果这个JWT签名是HMAC算法),或者需要服务端对公钥(如果这个WJT是数字化签名)
特别注意:对于JWS,荷载(声明部分)没有进行加密,所以,不要发送任何敏感信息.
5)关于JWE
JWE模式会对内容加密,而不是签名。JWT的声明会被加密。因此JWE带来了保密性。JWE可以被签名并附在JWS里。这样的话就可以同时加密和签名。因此得到了保密性(Confidentiality)、完整性(Integrity)、可认证(Authentication)。
6)那么对于客户端,如何分辨JWS或者JWE呢?
JWS的Header与JWE的Header是不同的,可以通过检查“alg”Header参数的值来区分。如果这个值表现为一个数字签名或者MAC的算法,或者是”none“,则它是一个JWS。
如果它表现为一个 Key Encryption, Key Wrapping, Direct Key Agreement, Key Agreement with Key Wrapping, or Direct Encryption algorithm。则它是一个JWE。
还可以通过Header里的“enc”(encryption algorithm)是否存在来判断,如果"enc"这个成员存在的话说明是JWE,否则的话就是JWS.