在express中進行token認證

什麼是Token

Token 是在服務端產生的,當客戶端傳來的用戶名/密碼驗證通過時,就會在服務器端生成一個Token返回給客戶端,這個Token中包含了用戶信息、過期時間等信息。客戶端接收到返回的token後將其保存,在有效時間內客戶端向服務器端發送請求時只需要帶上這個token即可,無需再帶上用戶名和密碼。

express中進行Token認證

  1.安裝 jsonwebtoken

npm install jsonwebtoken --save

   2. 在 public文件夾下新建 token.js 文件,用戶token的生成與解析

//用於生成和解析token
var jwt = require('jsonwebtoken');
var signkey = 'mes_qdhd_mobile_xhykjyxgs';
​
exports.setToken = function(username,userid){
  return new Promise((resolve,reject)=>{
    const token = jwt.sign({
      name:username,
      _id:userid
    },signkey,{ expiresIn:'1h' });
    resolve(token);
  })
}
​
exports.verToken = function(token){
  return new Promise((resolve,reject)=>{
    var info = jwt.verify(token.split(' ')[1],signkey);
    resolve(info);
  })
}
   3. 在 app.js 中進行token的相關配置,這裏有一點很關鍵,要配置有哪些路由是不需要認證的,比如說登錄接口,在未登錄前客戶端是沒有token的,token必須要通過登錄獲得,因此這個接口必須不能進行token認證。
var vertoken = require('./public/token')
// 解析token獲取用戶信息
app.use(function(req, res, next) {
  var token = req.headers['authorization'];
  if(token == undefined){
    return next();
  }else{
    vertoken.verToken(token).then((data)=> {
      req.data = data;
      return next();
    }).catch((error)=>{
      return next();
    })
  }
});
//驗證token是否過期並規定哪些路由不用驗證
app.use(expressJwt({
  secret: 'mes_qdhd_mobile_xhykjyxgs'
}).unless({
  path: ['/login']//除了這個地址,其他的URL都需要驗證
}));
//當token失效返回提示信息
app.use(function(err, req, res, next) {
  if (err.status == 401) {
    return res.status(401).send('token失效');
  }
});

  4. 編寫登錄接口

router.post('/login', function(req, res, next) {
  var username = req.body.username;
  var password = req.body.password;
  //生成token
  settoken.setToken(username,userid).then((data)=>{
    res.json({ token: data });
  })
});

   5. 獲取數據接口

當未在請求頭中加入token時,是無法獲取到數據的

我們在請求頭中加入token認證信息,這裏要注意一點,一定要使用 Bearer token的格式,即在token前面要加上Bearer。 如下所示:

再次發送請求,可以看到返回了我們想要的信息。但是這個token不是永久有效的,它具有有效期時間,過了有效期當然這個token也就作廢了,需要重新登錄獲取新的token。

有的人按照上面的做法都是一樣的,但是爲什麼還是無法得到數據呢。

這裏有一點肯很容易被忽略,如果在express中設置了請求頭信息中沒有含有Authorization的話,後端是無法接收到token的。

app.all('*', (req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "content-type");
  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  res.header("Content-Type", "application/json;charset=utf-8");
  next();
});

這裏需要把 Authorization加入到請求頭中。

res.header("Access-Control-Allow-Headers", "content-type,Authorization");

與VUE對接

在VUE用使用axios請求,可以在axios的請求攔截器中配置token

//請求攔截器
instance.interceptors.request.use(    
    config => {        
        const token = store.state.token;
        token && (config.headers.Authorization = 'Bearer ' + token);        
        return config;    
    },    
    error => Promise.error(error)
)

還可以對不同的狀態碼進行相應的處理,這裏只舉例幾個

const toLogin = () => {
    router.replace({
        path: '/login',        
        query: {
            redirect: router.currentRoute.fullPath
        }
    });
}
const errorHandle = (status) => {
    // 狀態碼判斷
    switch (status) {
        // 401: 未登錄狀態,跳轉登錄頁
        case 401:
            toLogin()   //403 token過期,跳轉登錄頁
            break;
        case 403:
            // tip('登錄過期,請重新登錄');
            localStorage.removeItem('token');
            store.commit('loginSuccess', null);
            setTimeout(() => {
                toLogin();
            }, 1000);
            break;
        // 404請求不存在
        case 404:
            console.log('請求資源不存在');
            break;
        // default:
}}

往期推薦

Chrome的小恐龍被我“開掛”了,看我如何用一行代碼然它擁有不死之身

用原生JS實現VUE的響應式原理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章