上一讲利用Passport实现了发放令牌的中间件,这一讲来实现验证令牌的中间件。
前面说到,端点根据需不需要验证信息可以分为三类:不需要,需要和可有可无。
第一类不需要验证。
第二类必需验证信息,比如用户发表新的博文时,必须把后端签发的令牌同添加博文的请求一起传给后端。
第三类端点,比如返回某个标签下的所有博文列表,请求里可以不带令牌,但是如果有合法的令牌的话,就返回与用户身份相关的额外信息,比如该用户是否为列表里的博文点过赞。对应第二三类端点,得有两套不同的逻辑块来负责验证用户身份:必需验证信息的和可以不用验证信息的,即是说,我们这一讲要实现的其实是两个不同的中间件。
新建文件routes/auth.js
,先导入所需的依赖:
const secret = require('../config').secret;
const jwt = require('express-jwt');
验证令牌需要用到签发令牌的同一口令,所以从config/index.js
中导入secret
。重复一遍,在开发环境,secret
的值是写在文件中的,而在生产环境,它的值是从环境变量中读取的。
具体到验证令牌中间件的代码实现,我们会用到express-jwt这个包(没错,安装过了)。这个包可以很方便地按照传入的参数,生成Express中间件。这里可以查阅它所接受的所有配置选项。
继续写入如下的代码:
const jwt = require('express-jwt');
const secret = require('../config').secret;
// +++
function getTokenFromHeader(req) {
var authHeader = req.header('authorization');
if (!authHeader) return null;
const [name, token] = authHeader.split(' ');
if (name === 'Token' && token)
return token;
return null;
}
const auth = {
required: jwt({
secret,
userProperty: 'payload',
getToken: getTokenFromHeader
}),
optional: jwt({
secret,
userProperty: 'payload',
credentialsRequired: false,
getToken: getTokenFromHeader
})
};
// +++
其中getTokenFromHeader
是一个辅助函数。从名字可以看出来,我们用它从请求头中抽取JWT令牌。它检查Authorization
这个请求头(req.header
不区分大小写),返回所带的令牌或者null
。
接下来我们定义了两个中间件required
和optional
。它们都是由express-jwt
自动生成的。我们给optional
传入了credentialsRequired: false
这条配置,表示就算没有令牌,验证也会成功。userProperty: payload
则表示令牌的信息会存储在req.payload
里面(req
是代表中间件所接受的代表请求的参数)。
最后,我们需要把上面定义的中间件暴露给后端应用的其它文件。在routes/auth.js
的最后加入:
module.exports = auth;
到此,验证用户身份的中间件都定义好了。接下来要做的就是把这些中间件整合到整个Express应用的中间件栈(也就是逻辑链条)中去。
网友评论