運行環境
該項目基於 node(v7.8.0版本以上) 和 mongodb 數據庫,因此電腦上需要安裝這兩個軟件,安裝教程自行百度。mongodb教程。如果實在不懂安裝,請勿下載代碼。
運行項目
此處已代表已經安裝完成了node和mongodb,下載代碼之后,目錄結構是這樣子的:
接下來需要安裝依賴,執行 npm install
,完成之后,目錄結構下多了一個 node_modules 的目錄,這些就是依賴文件。
接下來運行 mongodb服務,然后在項目根目錄下執行 node app.js
,運行node服務,然后在瀏覽器打開 http://localhost:3000 ,則可以正常訪問了。
如果想修改頁面,可以再執行 npm run serve
,運行 vue,訪問 http://localhost:8080 ,就可以了
需求分析
在前后端分離的開發中,通過 Restful API 進行數據交互時,如果沒有對 API 進行保護,那么別人就可以很容易地獲取並調用這些 API 進行操作。那么服務器端要如何進行鑒權呢?
Json Web Token 簡稱為 JWT,它定義了一種用於簡潔、自包含的用於通信雙方之間以 JSON 對象的形式安全傳遞信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對進行簽名。
所以,我們要給 API 加上 JWT 認證。
實現過程
首先用戶登錄時,輸入用戶名和密碼后請求服務器登錄接口,服務器驗證用戶名密碼正確后,生成token並返回給前端,前端存儲token,並在后面的請求中把token帶在請求頭中傳給服務器,服務器驗證token有效,返回正確數據。
代碼實現
生成token
這里注冊了個 /login
的路由,用於用戶登錄時獲取token。
const router = require('koa-router')();
const jwt = require('jsonwebtoken');
const userModel = require('../models/userModel.js');
router.post('/login', async (ctx) => {
const data = ctx.request.body;
if(!data.name || !data.password){
return ctx.body = {
code: '000002',
data: null,
msg: '參數不合法'
}
}
const result = await userModel.findOne({
name: data.name,
password: data.password
})
if(result !== null){
const token = jwt.sign({
name: result.name,
_id: result._id
}, 'my_token', { expiresIn: '2h' });
return ctx.body = {
code: '000001',
data: token,
msg: '登錄成功'
}
}else{
return ctx.body = {
code: '000002',
data: null,
msg: '用戶名或密碼錯誤'
}
}
});
module.exports = router;
在驗證了用戶名密碼正確之后,調用 jsonwebtoken 的 sign() 方法來生成token,接收三個參數,第一個是載荷,用於編碼后存儲在 token 中的數據,也是驗證 token 后可以拿到的數據;第二個是密鑰,自己定義的,驗證的時候也是要相同的密鑰才能解碼;第三個是options,可以設置 token 的過期時間。
獲取token
接下來就是前端獲取 token,這里是在 vue.js 中使用 axios 進行請求,請求成功之后拿到 token 保存到 localStorage 中。這里登錄成功后,還把當前時間存了起來,除了判斷 token 是否存在之外,還可以再簡單的判斷一下當前 token 是否過期,如果過期,則跳登錄頁面
submit(){
axios.post('/login', {
name: this.username,
password: this.password
}).then(res => {
if(res.code === '000001'){
localStorage.setItem('token', res.data);
localStorage.setItem('token_exp', new Date().getTime());
this.$router.push('/');
}else{
alert(res.msg);
}
})
}
然后請求服務器端API的時候,把 token 帶在請求頭中傳給服務器進行驗證。每次請求都要獲取 localStorage 中的 token,這樣很麻煩,這里使用了 axios 的請求攔截器,對每次請求都進行了取 token 放到 headers 中的操作。
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
config.headers.common['Authorization'] = 'Bearer ' + token;
return config;
})
驗證token
通過 koa-jwt 中間件來進行驗證,用法也非常簡單
const koa = require('koa');
const koajwt = require('koa-jwt');
const app = new koa();
// 錯誤處理
app.use((ctx, next) => {
return next().catch((err) => {
if(err.status === 401){
ctx.status = 401;
ctx.body = 'Protected resource, use Authorization header to get access\n';
}else{
throw err;
}
})
})
app.use(koajwt({
secret: 'my_token'
}).unless({
path: [/\/user\/login/]
}));
通過 app.use 來調用該中間件,並傳入密鑰 {secret: 'my_token'}
,unless 可以指定哪些 URL 不需要進行 token 驗證。token 驗證失敗的時候會拋出401錯誤,因此需要添加錯誤處理,而且要放在 app.use(koajwt()) 之前,否則不執行。
如果請求時沒有token或者token過期,則會返回401。
運行效果
登陸
獲取用戶信息
無效請求
Node.js 使用 JWT 進行用戶認證
注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權