带你从零学会---基于JWT的接口权限验证

416 阅读3分钟

服务端配置JWT的方法

  1. 安装jsonwebtoken第三方工具包
npm i jsonwebtoken
  1. 引入jwt
var jwt = require('jsonwebtoken');
  1. 在控制器中生成token,并进行返回
router.get('/login', function (req, res, next) {
  var token = jwt.sign({ uid: '1', username: "zhangsan" }, 'this is sign', {
    expiresIn: 60*60*24
  });
  res.send({
    "token":token
  });
});

注意:sign函数接收的第一个参数表示的是要传递的信息,第二个参数相当于是签名,第三个参数接收的是一个配置对象,对象中可以设置token的过期时间。

  1. 安装basic-auth
npm install basic-auth
  1. 引入basic-auth
var auth = require('basic-auth')
  1. 获取到用户传来的token
const token = auth(req);

注意:通过postman传递token,可以通过下面的这种方式来进行传递。

image.png

  1. 验证token是否合法

下面的验证是在控制器中实现的,如果想要实现复用可以在中间件中实现。

router.get('/address', function (req, res, next) {

  const token = auth(req);
  if (token) {
    try {
      const decoded = jwt.verify(token.name, 'this is sign');
      if (decoded) {
        res.send({
          success: true,
          msg: "验证成功"
        })
      } else {
        res.send({
          success: false,
          msg: "token错误"
        })
      }
    } catch (error) {
      res.send({
        success: false,
        msg: error
      })
    }
  } else {
    res.send({
      success: false,
      msg: "token错误"
    })
  }
})
  1. 通过中间件复用验证token的逻辑
//权限判断的中间件
var authMiddleWare = function (req, res, next) {

  var result = auth(req);
  if (!result) {
    res.send({
      success: false,
      msg: "token错误"
    });
    return;
  }
  try {
    var decoded = jwt.verify(result.name, 'this is sign');
    console.log(decoded);
    next();
  } catch (error) {
    res.send({
      success: false,
      msg: error
    })
  }
}
  1. 在路由匹配时,通过第二个参数来加入中间件判断
router.get('/address',authMiddleWare, function (req, res, next) {
  res.send({
    success: true,
    result:[
      {"name":"张三","address":"北京市"},
      {"name":"李四","address":"北京市"},
      {"name":"王五","address":"北京市"}
    ]      
  });
});

前端携带token进行请求的方法

  1. 首先将axios挂载到Vue的原型对象上。
Vue.prototype.$http = axios;
  1. 前端获取token的方法

下面的这个方法不仅获取到了token,而且将token保存到了localstorage上。

  this.$http
    .get("http://localhost:3000/api/login")
    .then(function(response) {         
      console.log(response.data.token);

      //保存用户信息 和 token
      localStorage.setItem('token',response.data.token);
    })
    .catch(function(error) {        
      console.log(error);
    });
  1. 前端携带token发送请求
getAddress() {
  var token=localStorage.getItem('token');
  this.$http
    .get("http://localhost:3000/api/address?uid=1&address_id=345", {
      auth: {
        username: token,
        password: 'sign'
      }
    })
    .then(function(response) {
      console.log(response);
    })
    .catch(function(error) {
      console.log(error);
    });
}

Egg.js中使用egg-jwt实现接口权限验证

  1. 安装egg-jwt
cnpm i egg-jwt --save
  1. 在config下的plugin.js中进行配置
jwt: {
    enable: true,
    package: 'egg-jwt'
  }
  1. 在config.default.js下配置密钥
  // 配置JWT的密钥
  config.jwt = {
    secret: "123456xxx"
  }
  1. 通过控制器请求指定路由返回token
  async login() {
    const token = this.app.jwt.sign({foo: 'bar'},this.app.config.jwt.secret,{
      expiresIn: 60*60*2
    });
    this.ctx.body = {
      "success": true,
      "token": token
    }
  }
  1. 配置指定路由需要进行token验证

只需在路由的第二个参数上进行配置即可。

router.get(`/api/v1`,app.jwt, controller.api.v1.index);

注意在egg.js中使用的不是basic auth,而是bearer token,如果想要通过测试工具进行测试可以使用VSCode中的插件Postcode。

image.png

  1. 由于egg.js中使用的不是basic auth,因此前端携带token的方式也要进行改变。
getIndex() {
  var api = "http://localhost:7001/api/v1";
  this.Axios.get(api, {
    headers: {
      Authorization: "Bearer " + this.token,
    },
  })
    .then((response) => {
      console.log(response.data);
    })
    .catch((err) => {
      console.log(err);
    });
}

上文演示的都是get请求携带token的方法,下面我们演示下post请求如何携带token。

addPeopleInfo() {
  var api = "http://localhost:7001/api/v1/addPeopleInfo";
  this.Axios.post(api, {
    tableId: 12,
    pNum: 4,
    pMark: "不要辣椒",
  },{
    headers: {
      Authorization: "Bearer " + this.token,
    },
  })
    .then((response) => {
      console.log(response.data);
    })
    .catch((err) => {
      console.log(err);
    });
}