菜单

Node.js 应用:Koa2 使用 JWT 实行鉴权

2019年5月4日 - CSS/CSS3

前言

在前后端分离的费用中,通过 Restful API 进行多少交互时,假诺未有对 API
进行体贴,那么人家就足以很轻松地获得并调用那些 API
举办操作。那么服务器端要什么开始展览鉴权呢?

Json Web Token 简称为
JWT,它定义了1种用于简洁、自包罗的用来通讯双方之间以 JSON
对象的花样安全传递信息的章程。JWT 能够运用 HMAC 算法或然是 TucsonSA
的公钥密钥对拓展具名。

说得就如跟真的平等,那么到底要怎么开始展览求证呢?

图片 1

率先用户登陆时,输入用户名和密码后呼吁服务器登入接口,服务器验证用户名密码正确后,生成token并再次回到给前端,前端存款和储蓄token,并在前面包车型大巴乞请中把token带在请求头中传给服务器,服务器验证token有效,重临准确数据。

既是服务器端使用 Koa二 框架进行支付,除了要使用到 jsonwebtoken
库之外,还要选取1个 koa-jwt 中间件,该中间件针对 Koa 对 jsonwebtoken
进行了包装,使用起来特别有益于。上面就来探视是如何使用的。

前言

生成token

这里登记了个 /login 的路由,用于用户登6时取得token。

const router = require('koa-router')();
const jwt = require('jsonwebtoken');
const userModel = require('../models/userModel.js');

router.post('/login', async (ctx) => {
    const data = ctx.request.body;
    if(!data.name || !data.password){
        return ctx.body = {
            code: '000002',
            data: null,
            msg: '参数不合法'
        }
    }
    const result = await userModel.findOne({
        name: data.name,
        password: data.password
    })
    if(result !== null){
        const token = jwt.sign({
            name: result.name,
            _id: result._id
        }, 'my_token', { expiresIn: '2h' });
        return ctx.body = {
            code: '000001',
            data: token,
            msg: '登录成功'
        }
    }else{
        return ctx.body = {
            code: '000002',
            data: null,
            msg: '用户名或密码错误'
        }
    }
});

module.exports = router;

在注解了用户名密码正确之后,调用 jsonwebtoken 的 sign()
方法来生成token,接收几个参数,第一个是载荷,用于编码后存款和储蓄在 token
中的数据,也是认证 token
后能够获得的数量;第叁个是密钥,自个儿定义的,验证的时候也是要壹致的密钥才干解码;第几个是options,可以设置
token 的过期时间。

在上下端分离的支出中,通过 Restful API 进行数量交互时,如若没有对 API
举行保证,那么人家就足以很轻松地获得并调用这个 API
举行操作。那么服务器端要什么开始展览鉴权呢?

获取token

接下去便是前者获取 token,这里是在 vue.js 中利用 axios
举行呼吁,请求成功以后获得 token 保存到 localStorage
中。这里登入成功后,还把最近时间存了4起,除了决断 token
是不是存在之外,还足以再轻易的推断一下当下 token
是不是过期,借使过期,则跳登六页面

submit(){
    axios.post('/login', {
        name: this.username,
        password: this.password
    }).then(res => {
        if(res.code === '000001'){
            localStorage.setItem('token', res.data);
            localStorage.setItem('token_exp', new Date().getTime());
            this.$router.push('/');
        }else{
            alert(res.msg);
        }
    })
}

下一场请求服务器端API的时候,把 token
带在请求头中传给服务器举行验证。每一趟请求都要博取 localStorage 中的
token,那样很辛苦,这里运用了 axios 的哀求拦截器,对每一遍请求都实行了取
token 放到 headers 中的操作。

axios.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    config.headers.common['Authorization'] = 'Bearer ' + token;
    return config;
})

Json Web Token 简称为
JWT,它定义了壹种用于简洁、自包蕴的用于通讯双方之间以 JSON
对象的样式安全传递音信的法子。JWT 能够行使 HMAC 算法大概是 索罗德SA
的公钥密钥对开始展览签订契约。

验证token

因此 koa-jwt 中间件来张开说明,用法也格外轻便

const koa = require('koa');
const koajwt = require('koa-jwt');
const app = new koa();

// 错误处理
app.use((ctx, next) => {
    return next().catch((err) => {
        if(err.status === 401){
            ctx.status = 401;
            ctx.body = 'Protected resource, use Authorization header to get access\n';
        }else{
            throw err;
        }
    })
})

app.use(koajwt({
    secret: 'my_token'
}).unless({
    path: [/\/user\/login/]
}));

经过 app.use 来调用该中间件,并传播密钥 {secret: 'my_token'},unless
能够钦命哪些 UCRUISERL 无需实行 token 验证。token
验证败北的时候会抛出401漏洞非常多,因而须要增添错误管理,而且要放在
app.use(koajwt()) 从前,不然不进行。

1旦请求时不曾token或然token过期,则会回来40壹。

说得好像跟真的一模二样,那么毕竟要怎么举行认证呢?

解析koa-jwt

大家地方使用 jsonwebtoken 的 sign() 方法来变化 token 的,那么 koa-jwt
做了些什么帮大家来注脚 token。

图片 2

resolvers/auth-header.js

module.exports = function resolveAuthorizationHeader(ctx, opts) {
    if (!ctx.header || !ctx.header.authorization) {
        return;
    }
    const parts = ctx.header.authorization.split(' ');
    if (parts.length === 2) {
        const scheme = parts[0];
        const credentials = parts[1];
        if (/^Bearer$/i.test(scheme)) {
            return credentials;
        }
    }
    if (!opts.passthrough) {
        ctx.throw(401, 'Bad Authorization header format. Format is "Authorization: Bearer <token>"');
    }
};

在 auth-header.js 中,决断请求头中是否带了 authorization,假设有,将
token 从 authorization 中分离出来。假设没有authorization,则表示了客户端从未传 token 到服务器,那时候就抛出 401错误状态。

第三用户登入时,输入用户名和密码后呼吁服务器登入接口,服务器验证用户名密码精确后,生成token并回到给前端,前端存款和储蓄token,并在背后的伸手中把token带在请求头中传给服务器,服务器验证token有效,再次来到正确数据。

verify.js

const jwt = require('jsonwebtoken');

module.exports = (...args) => {
    return new Promise((resolve, reject) => {
        jwt.verify(...args, (error, decoded) => {
            error ? reject(error) : resolve(decoded);
        });
    });
};

在 verify.js 中,使用 jsonwebtoken 提供的 verify()
方法进行表达重回结果。jsonwebtoken 的 sign() 方法来变化 token 的,而
verify() 方法则是用来注脚和剖析 token。假设 token
无效,则会在此方式被认证出来。

既是服务器端使用 Koa二 框架进行开拓,除了要运用到 jsonwebtoken
库之外,还要选取多少个 koa-jwt 中间件,该中间件针对 Koa 对 jsonwebtoken
进行了包装,使用起来更为有利于。上边就来探视是怎么着采用的。

index.js

const decodedToken = await verify(token, secret, opts);
if (isRevoked) {
    const tokenRevoked = await isRevoked(ctx, decodedToken, token);
    if (tokenRevoked) {
        throw new Error('Token revoked');
    }
}
ctx.state[key] = decodedToken;  // 这里的key = 'user'
if (tokenKey) {
    ctx.state[tokenKey] = token;
}

在 index.js 中,调用 verify.js 的法子实行求证并分析 token,得到地方实行sign() 的数据 {name: result.name, _id: result._id},并赋值给
ctx.state.user,在调控器中便得以一直通过 ctx.state.user 拿到 name
_id

生成token

安全性

这边登记了个 /login 的路由,用于用户登6时得到token。

总结

那上头就是 jwt
基本的流程,那只怕不是最周到的,但在很多报到中应用已经丰盛了。
地方的代码只怕不够具体,这里运用 Koa + mongoose + vue.js 完毕的一个例证

jwt-demo,能够做为参考。

const router = require('koa-router')();
const jwt = require('jsonwebtoken');
const userModel = require('../models/userModel.js');

router.post('/login', async (ctx) => {
  const data = ctx.request.body;
  if(!data.name || !data.password){
    return ctx.body = {
      code: '000002',
      data: null,
      msg: '参数不合法'
    }
  }
  const result = await userModel.findOne({
    name: data.name,
    password: data.password
  })
  if(result !== null){
    const token = jwt.sign({
      name: result.name,
      _id: result._id
    }, 'my_token', { expiresIn: '2h' });
    return ctx.body = {
      code: '000001',
      data: token,
      msg: '登录成功'
    }
  }else{
    return ctx.body = {
      code: '000002',
      data: null,
      msg: '用户名或密码错误'
    }
  }
});

module.exports = router;

越多文章:lin-xin/blog

在验证了用户名密码精确之后,调用 jsonwebtoken 的 sign()
方法来生成token,接收八个参数,第5个是载荷,用于编码后存款和储蓄在 token
中的数据,也是认证 token
后方可得到的多少;第3个是密钥,本人定义的,验证的时候也是要平等的密钥技术解码;第陆个是options,能够安装
token 的逾期时间。

获取token

接下去正是前者获取 token,这里是在 vue.js 中接纳 axios
实行呼吁,请求成功之后获得 token 保存到 localStorage
中。这里登六成功后,还把近来时光存了起来,除了推断 token
是不是留存之外,还足以再轻巧的判断一下当下 token
是不是过期,借使过期,则跳登入页面

submit(){
  axios.post('/login', {
    name: this.username,
    password: this.password
  }).then(res => {
    if(res.code === '000001'){
      localStorage.setItem('token', res.data);
      localStorage.setItem('token_exp', new Date().getTime());
      this.$router.push('/');
    }else{
      alert(res.msg);
    }
  })
}

下一场请求服务器端API的时候,把 token
带在请求头中传给服务器进行验证。每一回请求都要取得 localStorage 中的
token,那样很艰难,这里运用了 axios 的呼吁拦截器,对每回请求都实行了取
token 放到 headers 中的操作。

axios.interceptors.request.use(config => {
  const token = localStorage.getItem('token');
  config.headers.common['Authorization'] = 'Bearer ' + token;
  return config;
})

验证token

由此 koa-jwt 中间件来拓展验证,用法也10分轻易

const koa = require('koa');
const koajwt = require('koa-jwt');
const app = new koa();

// 错误处理
app.use((ctx, next) => {
  return next().catch((err) => {
    if(err.status === 401){
      ctx.status = 401;
      ctx.body = 'Protected resource, use Authorization header to get access\n';
    }else{
      throw err;
    }
  })
})

app.use(koajwt({
  secret: 'my_token'
}).unless({
  path: [/\/user\/login/]
}));

通过 app.use 来调用该中间件,并传播密钥 {secret: ‘my_token’} ,unless
能够内定哪些 UPAJEROL 无需实行 token 验证。token
验证失败的时候会抛出401荒唐,由此须求增加错误管理,而且要放在
app.use(koajwt()) 从前,否则不进行。

万1请求时不曾token或许token过期,则会回到40一。

解析koa-jwt

我们地点运用 jsonwebtoken 的 sign() 方法来扭转 token 的,那么 koa-jwt
做了些什么帮大家来证实 token。

resolvers/auth-header.js
module.exports = function resolveAuthorizationHeader(ctx, opts) {
  if (!ctx.header || !ctx.header.authorization) {
    return;
  }
  const parts = ctx.header.authorization.split(' ');
  if (parts.length === 2) {
    const scheme = parts[0];
    const credentials = parts[1];
    if (/^Bearer$/i.test(scheme)) {
      return credentials;
    }
  }
  if (!opts.passthrough) {
    ctx.throw(401, 'Bad Authorization header format. Format is "Authorization: Bearer <token>"');
  }
};

在 auth-header.js 中,判别请求头中是或不是带了 authorization,要是有,将
token 从 authorization 中分离出来。假若没有authorization,则代表了客户端从未传 token 到服务器,那时候就抛出 401错误状态。

verify.js

const jwt = require('jsonwebtoken');

module.exports = (...args) => {
  return new Promise((resolve, reject) => {
    jwt.verify(...args, (error, decoded) => {
      error ? reject(error) : resolve(decoded);
    });
  });
};

在 verify.js 中,使用 jsonwebtoken 提供的 verify()
方法开始展览表明重返结果。jsonwebtoken 的 sign() 方法来扭转 token 的,而
verify() 方法则是用来证实和剖析 token。假诺 token
无效,则会在此措施被认证出来。

index.js

const decodedToken = await verify(token, secret, opts);
if (isRevoked) {
  const tokenRevoked = await isRevoked(ctx, decodedToken, token);
  if (tokenRevoked) {
    throw new Error('Token revoked');
  }
}
ctx.state[key] = decodedToken; // 这里的key = 'user'
if (tokenKey) {
  ctx.state[tokenKey] = token;
}

在 index.js 中,调用 verify.js 的办法进行求证并分析 token,得到地方进行sign() 的数据 {name: result.name, _id: result._id} ,并赋值给
ctx.state.user ,在调节器中便足以一向通过 ctx.state.user 获得 name 和
_id 。

安全性

总结

那上边正是 jwt
基本的流水生产线,这大概不是最完美的,但在很多签到中应用已经足足了。

上面包车型客车代码或然不够具体,这里运用 Koa + mongoose + vue.js 落成的一个例子
jwt-demo,能够做为参考。

以上正是本文的全部内容,希望对大家的读书抱有帮忙,也希望大家多多援救脚本之家。

您可能感兴趣的篇章:

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图