node学习系列之终结篇-7-session+cookie安全验证,jwt安全验证

http请求特点是无状态的,也即是请求接口者未知,为了防止随意访问,加一个身份验证。在登录成功以后,发布一个加密字符串(用户信息相关),给前端,以后每次给后端请求接口,都要将加密字符串传递给后端来验证。

处理该问题总体有两种方式:

1、session+cookie 跨域不可用cookie,导致ip不一致时候容易出现问题,用起来麻烦

  • 需要用到的node插件有两个:cookie-parse和express-session
  • 使用该插件,登录成功后会自动生成cookie给前端

使用步骤:

在服务中引入插件并做配置:

const session = require('express-session');
const cookParse = require('cookie-parse');
...
// 在需要拦截的地方进行中间件配置
app.use('/food',(req, res, next)=>{
  if(req.body.session.login){
    next()
  }else{
    res.send({success: false, message: '没有登录,请先登录'});
  }
}, foodRouter);
app.use(session({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true,
  cookie: { masAge: 60 * 1000 * 60 } //设置过期时间
}));

在登录接口中,登录成功以后,由于安装了express-session插件并配置了,在req.body.session能获取到seeeion值,同理也可以赋值,登录成功后,做如下处理:

router.post('/login', (req,res)=>{
  const {us, ps}=req.body;
  if(us&&ps){
    User.find({name: us,pass: ps}).then(data=>{
      if(data.length>0){
          // 给session设置值
        req.session.login=true;
        req.session.name=us;
        res.send({success: true, message: '登录成功', user:data});
      }else{
        res.send({success: false, message: '账号或者密码错误'});
      }
    }).catch(error=>{
      res.send({success:false, message: '程序错误请联系管理员'});
    })
  }else{
    res.send({success: false, message: '缺少参数'})
  }
})

之后再访问food模块内容东西,由于配置了拦截器,如果获取不到session中的login,就会返回失败信息。

  • 如何清除session呢?

在退出接口做如下配置就可:

router.get('/logOut', (req,res)=>{
  req.session.destroy();
  res.send({message: '退出成功', success: true})
});

这样就会清除掉cookie信息,并清除登录session。

2、使用jwt是json web token 简写

前端登录时候,后端返回一个token,以后每次调接口都要传递此token,没有token就会验证不通过,禁止访问。

jwt又分为两类,一类是对称性加密,一种是非对称加密。

node学习系列之终结篇-7-session+cookie安全验证,jwt安全验证_第1张图片
打开jwt官网,就会发现有三部分组成,一个是头信息,确定使用那种加密方式,图中使用的是hs256(哈希256),第二个是参数,第三个是私钥通过你随便输入的私钥,输的越乱越好。通过加密算法将前两个合成一个东西,生成蓝色的内容,就是token。注意不要在payload中放密码信息,通过官网能解析出来token。

1、下面使用node的jsonwebtoken插件来实现对称性加密,默认采用hs256:

// 简单实现
const jwt=require('jsonwebtoken');
const payload={
  us: 'ling',
  login: true,
};
const screat = 'jsladfjklsdjlkfjlk;asdjlfk;jaskldjfklas';
// 生成token
const token=jwt.sign(payload, screat, {expiresIn: 300}); // hs256 数据 载荷  screat私钥 过期时间,单位是秒,设为5分钟过期
// 验证token合法性
jwt.verify(token, screat, (err,data)=>{
  console.log(err, data)
})
console.log(token);

2、封装函数

const jwt=require('jsonwebtoken');
const screat = 'jsladfjklsdjlkfjlk;asdjlfk;jaskldjfklas';
// 生成token
function createToken(payload){
  return jwt.sign(payload, screat, { expiresIn: 180 });// 设置过期时间为3分钟
}
// 验证token合法性
function checkedToken(token) {
  return new Promise((resolve, reject)=>{
    jwt.verify(token, screat, (err, data)=>{
      if(err){reject('token验证失败')}
      resolve(data);
    })
  })
}
module.exports={
  createToken,
  checkedToken,
}

将上述封装函数放在utils文件下,文件命名为jwt。在登录成功接口,做如下处理:

const JWT=require('../utils/jwt');
router.post('/login', (req,res)=>{
  const {us, ps}=req.body;
  if(us&&ps){
    User.find({name: us,pass: ps}).then(data=>{
      if(data.length>0){
        const token=JWT.createToken({login: true, name: us});
        res.send({success: true, message: '登录成功', user:data, token});
      }else{
        res.send({success: false, message: '账号或者密码错误'});
      }
    }).catch(error=>{
      res.send({success:false, message: '程序错误请联系管理员'});
    })
  }else{
    res.send({success: false, message: '缺少参数'})
  }
})

前端将token信息保存到本地,以后调用接口将该token传进去。

后端在需要登录才能访问的功能下,服务中加如拦截器:

const JWT=require('../utils/jwt');
app.use('/food',(req, res, next)=>{
  const {token}=req.body;
  JWT.checkedToken(token).then((data)=>{
    next()
  }).catch((err)=>{
    res.send({success: false, message: 'token无效'});
  })
}, foodRouter);

你可能感兴趣的:(node,安全验证,token,jwt,session,cookie)