Node.js使用token進行認證的簡單示例

本文只介紹簡單的應用,關於json web token的具體介紹以及原理請參考阮一峯老師的JSON Web Token 入門教程html

使用的Node框架是koa2,前端發送ajax請求使用axios前端

首先建立工程目錄:
image.png
static中存放靜態資源,views存放前端模板,server.js爲後端代碼。node

安裝必要的依賴項:ios

"dependencies": {
    "@koa/router": "^8.0.8",
    "jsonwebtoken": "^8.5.1",
    "koa": "^2.12.0",
    "koa-bodyparser": "^4.3.0",
    "koa-ejs": "^4.3.0",
    "koa-jwt": "^4.0.0",
    "koa-static": "^5.0.0",
    "koa-views": "^6.2.2"
  }

在server.js中添加代碼來建立一個簡單的後端程序,因爲網上有太多相關示例代碼,在此再也不贅述。git

const koa = require('koa');
const app = new koa();
const bodyParser = require('koa-bodyparser');
const router = require('@koa/router')();
const views = require('koa-views');
const static = require('koa-static');
const path = require('path');

app.use(bodyParser());
app.use(views(__dirname + '/views', {
  map: { html: 'ejs' }
}));

app.use(static(path.join(__dirname, '/static')));

router.get('/', ctx => ctx.render('index'));

app
  .use(router.routes())
  .use(router.allowedMethods());

app.listen(8080, () => {
  console.log('server is running at port 8080');
});

const path = require('path');後添加代碼:github

const { sign } = require('jsonwebtoken');
const secret = 'demo';
const jwt = require('koa-jwt')({ secret });

sign方法用來生成toekn,secret爲自定義的祕鑰,jwt提供路有權限控制的功能,它會對須要限制的資源請求進行檢查。web

建立路由login:ajax

router.post('/login', ctx => {
  const { user } = ctx.request.body;
  if (user && user.username === 'vip') {
    let { username } = user;
    const token = sign({ username }, secret, { expiresIn: '1h' });
    ctx.body = {
      message: 'GET TOKEN SUCCESS',
      status: 200,
      token
    }
  } else {
    ctx.body = {
      message: 'GET TOKEN FAILED',
      status: 500
    }
  }
});

如代碼所示,當前端發送的請求體中包含一個user對象而且username爲vip時將生成一個token返回給前端,這裏用到了前文提到的sign方法,第一個參數是用戶信息,第二個參數是自定義的key,第三個參數是個option,此處只定義了過時時間。json

再建立路由info:axios

router.get('/info', jwt, ctx => {
  ctx.body = { message: `Welcome ${ctx.state.user.username}!`};
});

與平時看到的路由代碼稍有不一樣,這裏增長了一個jwt中間件,用來對權限進行控制,若是沒法經過驗證,則不會執行以後的代碼。在前文生成token後,會把用戶名存入ctx.state.user中,在這裏能夠直接獲取。

這時在控制檯中輸入node server啓動該項目

打開index.html文件,添加一個簡單的表單和一個按鈕,並引入axios:

<form>
  <input type="text" name="username">
  <button id="submit">提交</button>
</form>
<button id="get">獲取</button>
<script src="/vendors/axios.min.js"></script>

首先添加登陸的邏輯:

document.querySelector('#submit').addEventListener('click', e => {
    e.preventDefault();
    const username = document.querySelector('input[name="username"]').value;
    axios.post('/login', { user: { username } })
      .then(response => {
        response = response.data;
        const { status, token, message } = response;
        if (status === 200) {
          localStorage.setItem('token', token);
        }
        alert(message);
      })
      .catch(error => alert(error.toString()));
  });

這裏將服務端生成的token存入localStorage以便下次使用。

當在輸入框中輸入vip並點擊提交按鈕,後端返回以下格式的信息:

message: "GET TOKEN SUCCESS"
status: 200
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InZpcCIsImlhdCI6MTU5MDMyOTkxOSwiZXhwIjoxNTkwMzMzNTE5fQ.PsyLYmr-pDxxdtrBEvMccVtBr9-xtOAHdZKen4FP34c"

而後再添加獲取邏輯:

document.querySelector('#get').addEventListener('click', e => {
    e.preventDefault();
    const instance = axios.create({ headers: { authorization: `Bearer ${localStorage.getItem('token')}` } });
    instance.get('/info')
      .then(response => {
        response = response.data;
        console.log(response)
        alert(response.message);
      })
      .catch(error => alert(error.toString()));
  });

此處用到了axios.create方法,該方法能夠在請求頭中添加token信息。用localStorage中獲取token並拼成形如authorization: Bearer token的形式,而後再用示例發送get請求。

此時再點擊獲取按鈕,會提示:
image.png
證實token是有效的。

此時去Application中把localStorage記錄清除掉,再點擊獲取按鈕,提示:
image.png
證實攔截成功。

完整示例能夠去個人GitHub查看並下載,若有疑問歡迎留言討論。

相關文章
相關標籤/搜索