web前端

token鉴权中间件

2022-05-24  本文已影响0人  姜治宇

登录模块

登录模块之前是采用cookie+session的方式来实现的,但这种方式有个最大的缺点,就是在nginx做负载均衡时比较麻烦,将sesssion存入redis仍然是个十分糟糕的选择,宝贵的内存资源不是用来存储会话这种无关紧要数据的。

token鉴权

我们在服务端摒弃对session的记录,改用token鉴权的方式来实现登录。具体做法是:
1、客户端将用户名和密码等信息提交到服务端;
2、服务端接收参数,查表,拉取用户信息;
3、将用户信息加密成一个特殊字符串,然后返回给客户端(token);
4、客户端本地保存token,在每个api请求都带上token(请求拦截);
5、服务端通过token中间件,对每个api请求进行鉴权,符合要求的就返回具体信息。

代码实现

以express为例,我们先生成一个项目。

npm install express -g
npm install express-generator -g
express testlogin

然后安装jwt相关的包,一共是两个。一个是用来生成token的,一个是鉴权的中间件。

npm install jsonwebtoken -S
npm install express-jwt -S

我们在登录接口生成token,并返回客户端。
users.js:

var express = require('express');
var router = express.Router();
const jwt = require('jsonwebtoken');
/* GET users listing. */
router.get('/list',function(req,res,next){
  res.send({
    status:0,
    msg:'登录成功'
  });
});
//登录
router.post('/login', function (req, res, next) {
  //获取参数信息
  //查库
  //用户信息
  let user = {
    status: 0,
    info: {
      username: 'jack',
      password: '123456',
      age: 16
    }

  };
  //秘钥
  let secretkey = 'jzy@2020';
  let token = jwt.sign({
    username: user.info.username
  }, secretkey, {
    expiresIn: '12h'
  });
  res.send({
    status: 0,
    msg: 'login ok',
    token: `Bearer ${token}`
  });
});

module.exports = router;

然后在入口app.js做中间件的鉴权即可。

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var { expressjwt: jwt } = require('express-jwt');

//路由
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();
app.use(jwt({ secret: 'jzy@2020', algorithms: ["HS256"] }).unless({
  path: ['/users/login']
}));

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  if (err.name === 'UnauthorizedError') {
    return res.send({ status: -1, msg: '身份认证失败' });
  }
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

鉴权中间件的unless方法是排除需要鉴权的路由,这个可以用正则做路径匹配。

测试

不带token请求时: 1.png 带上token: 2.png
上一篇下一篇

猜你喜欢

热点阅读