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函數