node>=7.6.0
javascript
npm v3.2.2
java
这个模块可让你在你的KOA应用中经过使用JSON WEB TOKEN(如下简称JWT)认证HTTP请求node
这个文档作了一个很好的介绍.git
若是你使用KOA版本2.+,同时你有一个低于7.6版本的node. 安装koa-jwt@2github
主分支(Koajwt git仓库上的.译者注)上的koa-jwt版本3+使用async/await,因此必须是node 7.6以上web
若是你使用koa1,你须要从npm安装koa-jwt@1.这个代码在koa-v1分支上算法
$ npm install koa-jwtnpm
JWT认证中间件的认证经过使用JWT令牌(token,译者注).若是令牌有效,ctx.state.user(默认状况下)会被设置成解码的JSON对象,以便于在稍后的中间件中进行认证或访问控制.json
令牌一般被包产在一个名为Authorization的HTTP头中,但也能经过cookie来进行,可是也能够使用Cookie来提供令牌,只要在opts.cookie选项上设置为包含令牌的cookie的名称.也能够经过opts.getToken选项完成自定义的令牌检索.返回的函数应该匹配如下接口:api
/** * 自定义令牌解析器 * @this 传入中间件的CTX对象 * * @param {object} opts 中间件选项 * @return {String|null} 返回被解析的令牌,若是没有找到则返回null */
令牌解析顺序以下所示.第一个被解析的非空令牌将被用于验证
运行opts.getToken 函数
检查cookies(若是cookies被设置了)
检查承载令牌的认证头(header)
一般你在opts.secret中提供了一个单独的开放密钥,可是另外一个替代方案是在一个更靠前的中间件中设置ctx.state.secret
,一般是每一个请求中.若是这个属性存在,它将用来替换opts.secret中的密钥.
你能够提供一个异步的函数来让koa-jwt检查令牌是否被撤销.这个函数应该被设置再opts.isRevoked属性中.你提供的函数应该匹配如下接口:
/** * 你自定义的检索撤销解析器 * * @param {object} ctx 传递给中间件的CTX对象 * @param {object} token 令牌 * @param {object} user 令牌的内容 * @return {Promise} 若是令牌没有被销毁, Promise必须被解析为false,其余状况下(Promise解析为true或erro)令牌被销毁. */
var Koa = require('koa'); var jwt = require('koa-jwt'); var app = new Koa(); // Custom 401 handling if you don't want to expose koa-jwt errors to users app.use(function(ctx, next){ return next().catch((err) => { if (401 == err.status) { ctx.status = 401; ctx.body = 'Protected resource, use Authorization header to get access\n'; } else { throw err; } }); }); // Unprotected middleware app.use(function(ctx, next){ if (ctx.url.match(/^\/public/)) { ctx.body = 'unprotected\n'; } else { return next(); } }); // Middleware below this line is only reached if JWT token is valid app.use(jwt({ secret: 'shared-secret' })); // Protected middleware app.use(function(ctx){ if (ctx.url.match(/^\/api/)) { ctx.body = 'protected\n'; } }); app.listen(3000);
你也能够在某些条件下有条件的运行koa-jwt中间件:
var koa = require('koa'); var jwt = require('koa-jwt'); var app = new Koa(); // Middleware below this line is only reached if JWT token is valid // unless the URL starts with '/public' app.use(jwt({ secret: 'shared-secret' }).unless({ path: [/^\/public/] })); // Unprotected middleware app.use(function(ctx, next){ if (ctx.url.match(/^\/public/)) { ctx.body = 'unprotected\n'; } else { return next(); } }); // Protected middleware app.use(function(ctx){ if (ctx.url.match(/^\/api/)) { ctx.body = 'protected\n'; } }); app.listen(3000);
更多关于unless
的例子,请点击koa-unless
即便没有找到认证头,你也能够经过添加一个passthrough
选项来保证始终传递到下一个(中间件)
app.use(jwt( { secret: 'shared-secret', passthrough:true }))
经过这个选项,使得下游中间件能够基于ctx.state.user是否设置作出决定
若是你更喜欢使用另一个ctx key
来表示解码数据,只须要传入key属性,以下:
app.use(jwt({ secret: 'shared-secret', key: 'jwtdata' }));
此时解码数据能够经过ctx.state.jwtdata
获得(替换掉默认的ctx.state.user)
你一样能够指定audience
和/或issuer
app.use(jwt({ secret: 'shared-secret', audience: 'http://myapi/protected', issuer: 'http://issuer' }));
若是koa-jwt有设置一个expiration(exp),它将会被检查到.
若是存在tokenkey
选项,而且找到有效的令牌,原始令牌数据能够从随后的中间件中的ctx.state[opts.tokenKey]属性中获得.
这个模块也支持令牌标记为公钥/私钥对. 做为秘钥的替代,你能够经过Buffer指定一个Public key
var publicKey = fs.readFileSync('/path/to/public.pub'); app.use(jwt({ secret: publicKey }));
当sercret
选项是一个函数时,这个函数将会被每一个koa-jwt接受到,用于决定哪一个密钥会被用于验证JWT
这个方法的签名应该是这样的: (header) => [Promise(secret)]
, header表示令牌头, 若是想做为支持JWKS的令牌头的实例, 应当包含alg
和kid
:算法和密钥ID字段
经过使用 node-jwks-rsa 组件,这个选项也能够用于支持JWKS(JSON Web Set),以下:
const { koaJwtSecret } = require('jwks-rsa'); app.use(jwt({ secret: koaJwtSecret({ jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json', cache: true, cacheMaxEntries: 5, cacheMaxAge: ms('10h') }), audience: 'http://myapi/protected', issuer: 'http://issuer' }));
jsonwebtoken — JSON Web Token signing and verification
注意koa-v2版本的koa-jwt再也不支持从jsonwebtoken中导出sign,verify和decode函数