1、需求說明
在前后端分離開發中,前端使用Vue.js框架,通過axios發送異步HTTP請求,服務端就無法使用session的方式保存用戶的登錄資訊,因為客戶端的每一次異步請求在服務端都會被認為是一個新的session,我們可以使用jwt(jsonwebtoken)的方式實作用戶的校驗,
2、安裝相關依賴
服務端:
本文中使用Express作為服務端框架,需要在服務端安裝以下JWT依賴:
cnpm i jsonwebtoken --save
cnpm i express-jwt --save
前端:
在前端使用Vue.js框架,需要安裝axios用于發送HTTP請求:
cnpm i axios --save
3、代碼實作
3.1、服務端代碼
app.js入口檔案引入 express-jwt ,示例代碼如下:
var express = require('express');
var expressJwt = require('express-jwt');
var app = express();
app.use(expressJwt({
credentialsRequired:false,
secret: 'helloworld', //密鑰
algorithms: ['HS256'] //沒有此配置項,在jwt6.0.0版本會報錯:algorithms should be set
}).unless({
path: ['/login'] //設定不需要token驗證的路由
}))
express-jwt 會自動驗證請求頭中的 token 資訊,
在 routes/index.js 路由檔案中創建用于登錄和用戶查詢的路由,示例代碼如下:
var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
//用戶登錄的路由,此路由不會進行token校驗
router.post('/login', function(req, res, next) {
let {username,pwd} = req.body
//模擬資料庫查詢賬號密碼
if(username === 'admin' && pwd === '123456'){
//生成Token資訊jwt.sign(payload, secretOrPrivateKey, [options, callback])
//payload引數為保存到客戶端的用戶資訊,
//secretOrPrivateKey 為密鑰,要和 app.js 檔案中的 secret 的值保持一致
//option為配置項,expiresIn是token的有效時長,單位為秒,值也可以為字串,例如 '2d' 表示2天
let Token = jwt.sign({name: username,role: 1},'helloworld',{expiresIn: 60})
res.json({
code: 200,
token: 'Bearer '+Token //向客戶端回應的token前面必須添加 ’Bearer ’ 前綴
})
}else{
res.json({
code: 500
})
}
});
//查詢用戶資訊的路由,此路由會校驗token
router.get('/api/user/find', function(req,res,next){
res.json({
code: 200,
result: ['tom','jack','lily']
})
})
module.exports = router;
jwt.sign() 方法也可以使用異步加密的方式,示例代碼如下:
//使用異步的方式生成token
jwt.sign(
{name:username,role:1},
'helloworld',
{expiresIn:60},
function(err,token){
console.log(token)
}
)
3.2、前端代碼
views/Login.vue 用戶登錄組件,示例代碼如下:
<template>
<div>
<input type="text" v-model="username" placeholder="用戶名"></input>
<input type="password" v-model="pwd" placeholder="密碼"></input>
<button @click="login">登錄</button>
</div>
</template>
<script>
import axiost from 'axios'
export default {
data(){
return {
username: '',
pwd: ''
}
},
methods: {
login(){ //登錄按鈕點擊事件
axios.post("/login",{
username: this.username,
pwd: this.pwd
}).then(res=>{
if(res.data.code === 200){
//保存token資訊
localStorage.token = res.data.token
}
})
}
}
}
</script>
前端校驗token的方法有以下幾種:
(1)使用Vue的路由守衛校驗
// 在路由全域前置守衛中判斷 token 是否存在
router.beforeEach((to , from, next) => {
// 獲取 token
if (localStorage.token)) {
if (to.name === 'login') { // 如果用戶在login頁面
next('/');
} else {
next();
}
} else {
router.push('/login')
}
});
(2)在axios請求攔截器中添加token資訊
// axios請求攔截器
axios.interceptors.request.use(
config => {
if (localStorage.token) { // 判斷是否存在token
config.headers.authorization = localStorage.token;
}
return config;
},
err => {
return Promise.reject(err);
});
//axios回應攔截器
axios.interceptors.response.use(res => {
return res;
}, err=> {
if (err.response.status === 401) { //token校驗失敗,沒有訪問權限
//輸出授權失敗錯誤資訊
} else {
//輸出其他錯誤資訊
}
return Promise.reject(err);
}
);
也可以直接在 axios 實體函式中設定 headers ,示例代碼如下:
let instance = axios.create({
baseURL: 'http://localhost:3000',
headers:{
authorization: localStorage.getItem('token')
}
})
instance.get('/xxx')
3.3、服務端校驗token并獲取用戶資訊
在服務端可以使用 express-jwt 自動完成校驗,也可以手動完成校驗,我們還可以在服務端獲取保存到客戶端的用戶資訊,在服務端的 routes/index.js 路由檔案中撰寫一個用于token驗證的測驗路由,示例代碼如下:
var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
//用于驗證token并獲取用戶資訊
router.get('/yz', function(req,res,next){
//從請求頭中獲取token內容
let token = req.headers.authorization
//由于token中包含 'Bearer '前綴,需要把前綴去掉獲得token值
token = token.replace('Bearer ','')
let result = null;
try{
//jwt.verify(token,secretOrPublicKey,[options,callback]) 驗證token的合法性
// secretOrPublicKey 引數為密鑰,要和生成token的密鑰保持一致
result = jwt.verify(token,'helloworld')
console.log(result)
}catch(err){
console.error(err)
}
res.json({
result
})
})
module.exports = router;
在控制臺列印的結果為如下圖所示:

jwt.verify() 方法回傳的值為 jwt.sign() 方法中的 payload 物件引數,JWT 規定了7個官方欄位,供選用,分別是:
- iss (issuer):簽發人
- exp (expiration time):過期時間
- sub (subject):主題
- aud (audience):受眾
- nbf (Not Before):生效時間
- iat (Issued At):簽發時間
- jti (JWT ID):編號
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/281418.html
標籤:其他
上一篇:Linux--行程與執行緒總結
下一篇:阿里云服務器使用寶塔面板部署django專案——nginx1.18+uwsgi+python3.8.5+django3.1.4+mysql5.6.5
