Node.js 教程第十二篇——Token

DK_Lan發表於2019-02-16

Token

在計算機身份認證中是令牌(臨時)的意思,在詞法分析中是標記的意思。一般我們所說的的 token 大多是指用於身份驗證的 token

Token的特點

  • 隨機性
  • 不可預測性
  • 時效性
  • 無狀態、可擴充套件
  • 跨域

基於Token的身份驗證場景

  1. 客戶端使用使用者名稱和密碼請求登入
  2. 服務端收到請求,驗證登入是否成功
  3. 驗證成功後,服務端會返回一個 Token 給客戶端,反之,返回身份驗證失敗的資訊
  4. 客戶端收到 Token 後把 Token 用一種方式(cookie/localstorage/sessionstorage/其他)儲存起來
  5. 客戶端每次發起請求時都選哦將 Token 發給服務端
  6. 服務端收到請求後,驗證Token的合法性,合法就返回客戶端所需資料,反之,返回驗證失敗的資訊

Token 身份驗證實現 —— jsonwebtoken

先安裝第三方模組 jsonwebtoken npm install jsonwebtoken

const express = require(`express`)
const path = require(`path`)
const app = express();
const bodyParser = require(`body-parser`);
const jwt = require(`jsonwebtoken`);

app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(path.join(__dirname, `/`)));

app.all(`*`, function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Auth, Accept,X-Requested-With");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",` 3.2.1`)
    if(req.method=="OPTIONS") {
          res.sendStatus(200);/*讓options請求快速返回*/
    } else{
          next();
    }
});


app.get(`/createtoken`, (request, response) => {
    //要生成 token 的主題資訊
    let user = {
        username: `admin`,
    }
    //這是加密的 key(金鑰)
    let secret = `dktoken`;
    //生成 Token
    let token = jwt.sign(user, secret, {
        `expiresIn`: 60*60*24 // 設定過期時間, 24 小時
    })      
    response.send({status: true, token});
})

app.post(`/verifytoken`, (request, response) => {
    //這是加密的 key(金鑰),和生成 token 時的必須一樣
    let secret = `dktoken`;
    let token = request.headers[`auth`];
    if(!token){
        response.send({status: false, message: `token不能為空`});
    }
    jwt.verify(token, secret, (error, result) => {
        if(error){
            response.send({status: false});
        } else {
            response.send({status: true, data: result});
        }
    })
})

app.listen(88)

前端 ajax 請求時在請求頭中包含 Token

ajax 請求之 jQuery 篇

$.ajax({
    url: `verifytoken`,
    type: `post`,
    headers: {"auth": `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTIzNTQwNjY5LCJleHAiOjE1MjM2MjcwNjl9.ddkS5XEiMzvNQsk9UlMPhyxPSq5S_oh3Nq19eIm9AJU`},
    success: function(res){
        console.log(res)
    }
})

ajax 請求之 XMLHttpRequest 篇

var xhr = new XMLHttpRequest();
xhr.open("POST","verifytoken");
xhr.setRequestHeader(`auth`, `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTIzNTQwNjY5LCJleHAiOjE1MjM2MjcwNjl9.ddkS5XEiMzvNQsk9UlMPhyxPSq5S_oh3Nq19eIm9AJU`);
xhr.send();

ajax 請求之 axios 篇

import axios from `axios`
axios({
    url: url,
    params: _params || {},
    headers: {auth: window.sessionStorage.getItem(`dktoken`)}
}).then(res => {
    if(!res.data.status && res.data.error == "unauthorized"){
        router.push(`login`);
        return false;
    }
    resolve(res)
}).catch(error => {
    reject(error)
})

ajax 請求之 superagent 篇

import http from `superagent`
http.post(getUrl(path))
    .set(`Content-Type`, `application/x-www-form-urlencoded; charset=UTF-8`)
    .set(`auth`,  window.localStorage.getItem(`access_token`))
    .end((err, res) => {});

相關文章