koa2使用jwt鉴权
鉴权
对用户进行认证,是否拥有访问权。
此示例,鉴定的是用户是否有权访问某个接口(路由)。
认证方式
此示例使用 jwt 认证方式。jwt 是 json web token 的缩写。
jwt
jwt 由三个部分组成:
Header(头部) Payload(负载) Signature(签名)
生成token发给用户时是这样的Header.Payload.Signature
格式。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InJvamVyeW9uZyIsImlhdCI6MTYwMjYzNzYyOSwiZXhwIjoxNjAyNjM3NzQ5fQ.NdDjdFqTB1RrMGDQN1fy7a3prZdYuOPjGYM05qrXjyU
《JSON Web Token 入门教程》:http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
步骤
1、用户登录成功,后台使用jsonwebtoken
生成签名(token)发给用户。
2、用户请求接口时,需要在请求头(或在请求体中、url参数中、cookie中)携带签名(token),后台使用koa-jwt
做鉴权。
安装
https://github.com/auth0/node-jsonwebtoken
npm i jsonwebtoken
npm i koa-jwt
使用
1、生成 token
用户登录成功,生成 token 返回给用户。
const jsonwebtoken = require('jsonwebtoken');
const jwtSecret = '123456' // 密钥
const token = null
// 生成签名
jsonwebtoken.sign({ username: 'rojeryong' }, jwtSecret, { algorithm: 'HS256', expiresIn: '120s' }, function (err, jwtToken) {
if (!err) {
token = jwtToken
}
});
username:自定义内容。 jwtSecret:生成签名的密钥。 algorithm:加密方式。 expiresIn:有效期,数字,秒,也可以设置1d代表一天,1h代表一小时... function:回调。
如果不想使用 koajwt 鉴权,可以使用 jsonwebtoken.verify 自定义鉴权中间件来做鉴权,自定义鉴权可能比 koajwt 鉴权更灵活。
jsonwebtoken.verify(token, jwtSecret, function (err, decoded) {
if (err) {
// 不通过
console.log(JSON.stringify(err))
}else {
// 通过
console.log(decoded)
}
});
2、koajwt 全局鉴权
jsonwebtoken 使用纯数字类型密钥可能会报错,建议使用字符类型。
// app.js
const Koa = require('koa')
const app = new Koa()
const router = require('koa-router')()
const koaJwt = require('koa-jwt');
const jwtSecret = '123456' // 密钥,字符,使用数字类型可能会报错
// 静态目录
app.use(require('koa-static')(__dirname + '/public'), {
maxage: 30 * 24 * 60 * 60 * 1000, // 浏览器缓存时间
extensions: ['html'] // 开启html静态访问
})
// 从url、body 或者 cookie 中获取 token
app.use(async (ctx, next) => {
// url,body 的 token
let params = Object.assign({}, ctx.request.query, ctx.request.body);
// 请求头的 token
let token = ctx.request.header && ctx.request.header.authorization?ctx.request.header.authorization:(params.token?params.token:null)
// cookie 的token
if(!token) {
token = ctx.cookies.get('token') || null;
}
// 设置头部
ctx.request.header = { 'authorization': "Bearer " + token }
await next();
})
// 错误监听
app.use(async (ctx, next) => {
return next().catch((err) => {
if (err.status === 401) {
let message = err.originalError && err.originalError.message ? err.originalError.message : (err.message ? err.message : "Authentication Error")
ctx.throw(401, message)
} else {
throw err;
}
})
});
// 鉴权
app.use(koaJwt({ secret: jwtSecret }).unless({
// 放行的路由
path: ['/','/login','/favicon.ico',new RegExp(`^/hello`)]
}))
// 放行的路由
router.get('/', async (ctx, next) => {
ctx.response.body = '<h1>index page</h1>'
})
// 放行的路由
router.get('/login', async (ctx, next) => {
ctx.response.body = '<h1>login page</h1>'
})
router.get('/admin', async (ctx, next) => {
ctx.response.body = '<h1>admin page</h1>'
})
app.use(router.routes())
app.listen(4000, () => {
console.log('app started at port 127.0.0.1:4000...');
});
注意
app.use(koaJwt({ secret: jwtSecret }).unless({
// 放行的路由
path: ['/','/login','/favicon.ico',new RegExp(`^/hello`)]
}))
path:不需要鉴权的路由(开放访问的路由)。
优先获取请求头ctx.request.header.authorization
的 token,没有的话获取 body、url 参数或 cookie 的 token。
如果鉴权不通过,可以在错误监听回调里面处理错误,可以配合koa-onerror
使用。
错误监听代码应该写在鉴权代码之前,洋葱模型,发生错误后是不会继续往下执行的。
注意鉴权代码的位置,鉴权代码应该写在注册路由之前,写在koa-static
(用了的话)等中间件之后,否则,请求静态资源路径也被鉴权。
测试
运行app.js,分别访问以下路由。
http://localhost:4000
http://localhost:4000/login
http://localhost:4000/admin
除了放行的路由,如果不传 token 会提示错误。
携带 token 访问
在请求需要验证的路由时,在 body、url 或者 cookie 携带 token 即可。
ajax 请求时携带 token:
const axios = require('axios');
let option = {
method: 'get',
url: `http://localhost:4000/admin`,
params:{
token:'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InVzZXIuaWQiLCJpYXQiOjE2MDQ4OTM5NDYsImV4cCI6ODgwMDQ4MDc1NDZ9.e-DgPVoRIWXsQDi9RPp3cy6cweTrY-oo8bWLd163yxY'
}
}
await axios(option).then(res => {
if (res.status == 200) {
// ...
}
})
url 携带 tokn:
http://localhost:4000/admin?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InVzZXIuaWQiLCJpYXQiOjE2MDQ4OTM5NDYsImV4cCI6ODgwMDQ4MDc1NDZ9.e-DgPVoRIWXsQDi9RPp3cy6cweTrY-oo8bWLd163yxY
koa2 后端给前端设置 cookie:
// 后端代码
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InVzZXIuaWQiLCJpYXQiOjE2MDQ4OTM5NDYsImV4cCI6ODgwMDQ4MDc1NDZ9.e-DgPVoRIWXsQDi9RPp3cy6cweTrY-oo8bWLd163yxY"
ctx.cookies.set('token', token)
前端访问路由时会自动携带 token。
转载请注明来源:《 koa2使用jwt鉴权》- rojerYong's Blog
文章链接:https://www.eoway.cn /article/1604900889.html如果此文摘取了你的原创,请联系本站管理员,将对此文修改、删除处理。