express-jwt使用帮助

express-jwt是一个验证JsonWebTokens并设置req.user的connect/express中间件。此模块允许您使用Node.js应用程序中的JWT令牌验证HTTP请求。 JWT通常用于保护API端点,通常使用OpenID Connect发布。

Json web token结构

JWT 的三个部分依次如下:

  • Header(头部)
  • Payload(负载)
  • Signature(签名)

Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

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

上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串。

Payload

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

1
2
3
4
5
6
7
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号

除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。

1
2
3
4
5
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。这个 JSON 对象也要使用 Base64URL 算法转成字符串。

Signature

ignature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

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

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用”点”(.)分隔,就可以返回给用户。

基于JWT的身份验证流程

使用基于 JWT 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

jsonwebtoken的使用

jsonwebtoken是JSON Web Tokens在Nodejs平台的实现。它可以与express-jwt模块配合,在expressjs中实现基于JWT的身份验证。

安装步骤

1
npm install jsonwebtoken --save

使用帮助

在expressjs中主要使用该模块生成JSON Web Tokens。其接口定义为:

  • jwt.sign(payload, secretOrPrivateKey, [options, callback])
1
2
3
4
5
6
var token = jwt.sign({
userId: users[0].id
},
appConfig.secretOrPrivateKey, {
expiresIn: 60 * 60 * 6
});
  • jwt.verify(token, secretOrPublicKey, [options, callback])
1
2
3
// verify a token symmetric - synchronous
var decoded = jwt.verify(req.body.token.split(' ')[1], appConfig.secretOrPrivateKey);
var user = await models.User.findByPk(decoded.userId);
  • jwt.decode(token [, options])
1
2
3
4
5
6
7
// get the decoded payload ignoring signature, no secretOrPrivateKey needed
var decoded = jwt.decode(token);

// get the decoded payload and header
var decoded = jwt.decode(token, {complete: true});
console.log(decoded.header);
console.log(decoded.payload)

express-jwt的使用

安装帮助

1
npm install express-jwt --save

使用示例

1
2
3
4
5
6
7
8
9
10
app.use(expressJWT({
secret: appConfig.secretOrPrivateKey
}));

app.use(function(err, req, res, next) {
console.log(err);
if (err.name === 'UnauthorizedError') {
res.status(err.status || 401).send(err.message);
}
});

参考链接

  1. 什么是 JWT – JSON WEB TOKEN, by Dearmadman
  2. JSON Web Token 入门教程,by 阮一峰.
  3. Cookie,Session和Token会话知识整理,by jack huang.
  4. node-jsonwebtoken,by auth0.