文章参考

Introduction to JSON Web Tokens

JSON Web Token - 在Web应用间安全地传递信息

JSON Web Token

使用JWT规范在用户和服务器之间传递安全可靠的信息。
适合用于向Web应用传递一些非敏感信息。

JSON Web Token

JSON Web Token (JWT, sometimes pronounced /dʒɒt/) is a JSON-based open standard (RFC 7519) for creating access tokens that assert some number of claims.

For example, a server could generate a token that has the claim “logged in as admin” and provide that to a client. The client could then use that token to prove that it is logged in as admin.

The tokens are signed by the server’s key, so the client and server are both able to verify that the token is legitimate. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context. JWT claims can be typically used to pass identity of authenticated users between an identity provider and a service provider, or any other type of claims as required by business processes. The tokens can also be authenticated and encrypted.

JSON Web Token structure

头部(Header)

描述类型以及签名所用的算法

the type of the token, which is JWT, and the hashing algorithm being used, such as HMAC SHA256 or RSA.

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

进行Base64编码,之后的字符串就成了JWT的Header

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

载荷(Payload)

Claims are statements about an entity (typically, the user) and additional metadata. There are three types of claims: registered, public, and private claims.

1
2
3
4
5
6
7
8
9
{
"iss": "John Wu JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "jrocket@example.com",
"from_user": "B",
"target_user": "A"
}
iss: 该JWT的签发者
sub: 该JWT所面向的用户
aud: 接收该JWT的一方
exp(expires): 什么时候过期,这里是一个Unix时间戳
iat(issued at): 在什么时候签发的

将上面的JSON对象进行[base64编码]可以得到下面的字符串。这个字符串我们将它称作JWT的Payload(载荷)。

eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjox
NDQxNTk0NzIyLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9j
a2V0QGV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9
1
2
3
4
5
6
7
var base64url = require('base64url')
var header = {
"from_user": "B",
"target_user": "A"
}
console.log(base64url(JSON.stringify(header)))
// 输出:eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzIyLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9

签名(Signature)

To create the signature part you have to take the encoded header, the encoded payload, a secret(密钥), the algorithm specified in the header, and sign that.

使用HMAC SHA256 算法创建signature

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

将上面的两个编码后的字符串都用句号.连接在一起(头部在前),就形成了

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJKb2huI
Fd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzI
yLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0Q
GV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9

如果我们用mystar作为密钥的话,那么就可以得到我们加密后的内容

rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

最后将这一部分签名也拼接在被签名的字符串后面,我们就得到了完整的JWT,然后更改URL等(?jwt=字符串)

Do not put secret information in the payload or header elements of a JWT unless it is encrypted.