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又分爲兩類,一類是對稱性加密,一種是非對稱加密。

在這裏插入圖片描述
打開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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章