在例如身份驗證場景中,用戶一旦登陸,接下來的每一個請求都會包含jwt,用來驗證身份信息。因爲通訊雙方使用jwt對數據進行編碼,它的信息是通過簽名的,因此能夠確保信息的安全性。css
cookie缺點vue
jwt優勢ios
完整的jwt格式的輸出是以 . 分隔的三段Base64編碼 密鑰secret是保存在服務端的,服務端會根據這個密鑰進行生成token和驗證,因此須要保護好。git
express+vue+mongoose 後端app.js,包括註冊,登陸,獲取訂單接口github
let express = require('express')
let bodyParser = require('body-parser')//中間件
let jwt = require('jwt-simple')//jwt庫
//數據庫
let User = require('./model/user')
//監聽函數
let app = express()
let {secret} = require('./config')
//中間件必定是函數,處理髮回來的json類型,還有text,urlencoded(a=b&c=d)
app.use(bodyParser.json())
//防止跨域 request請求 response響應
app.use(function(req, res, next){
res.setHeader('Access-Control-Allow-Origin','*');//簡單點,接收全部
res.setHeader('Access-Control-Allow-Headers','Content-type,Authorization');
res.setHeader('Access-Control-Allow-Methods','GET,POST,DELETE,PUT,OPTIONS');
if(req.method === 'OPTIONS') {
res.end()
}else {
next()
}
})
//註冊
app.post('/reg', async function(req, res, next){
let user = req.body;
try {
user = await User.create(user) //在數據庫中插入數據
res.json({
code: 0,
data: {
user: {
id: user._id,
username: user.username
}
}
})
} catch (error) {
res.json({
code: 1,
data: '註冊失敗'
})
}
})
//登陸
app.post('/login', async function(req,res,next){
let user = req.body;
user = await User.findOne(user)//數據庫中查找
if(user) {
let token = jwt.encode({//編碼
id: user._id,
username: user.username
},secret);
res.json({//返回信息
code: 0,
data: { token }
})
}else {
res.json({
code: 1,
data: '用戶不存在'
})
}
})
// 用戶校驗 中間件
let auth = function(req, res, next){
//post模擬時 添加Headers Authorization: Bearer token的值
let authorization = req.headers['authorization']
if(authorization) {
let token = authorization.split(' ')[1];
try {
//看token是否合法,解碼,若是串改過token就解不出來,進入異常頁面
let user = jwt.decode(token, secret);
req.user = user;//後面就能夠拿到user,中間件用法
next();//下一步
} catch (error) {
console.log(error)
res.status(401).send('Not Allowed')
}
} else {
res.status(401).send('Not Allowed');
}
}
//發送請求,看看能不驗證成功auth,若是能夠拿到返回數據
app.get('/order', auth, function(req,res,next){
res.json({
code: 0,
data: {
user: req.user
}
})
})
app.listen(3000)
複製代碼
數據庫頁面web
// 操做數據庫
let mongoose = require('mongoose');
let {DB_URL} = require('../config');
mongoose.connect(DB_URL,{useNewUrlParser:true})
/**
* 鏈接成功
*/
mongoose.connection.on('connected', function () {
console.log('Mongoose connection open to ' + DB_URL);
});
/**
* 鏈接異常
*/
mongoose.connection.on('error',function (err) {
console.log('Mongoose connection error: ' + err);
});
//建立Schema數據模型
let UsrSchema = new mongoose.Schema({
username: String,
password: String
});
module.exports = mongoose.model('User', UsrSchema);
複製代碼
axios簡單封裝算法
import axios from 'axios'
import router from '../src/router'
axios.defaults.baseURL = 'http://localhost:3000'
//axios 攔截器對拿到的數據進行攔截
axios.interceptors.response.use(function(res){
if(res.data.code !== 0) {
return Promise.reject(res.data.data)
}
return res.data;
},res=>{
if(res.response.status === 401){ // 沒權限跳到登陸頁
router.history.push('/login');
}
return Promise.reject('Not Allowed');
});
//對發送的請求統一加上token,來驗證是不是本人登陸
axios.interceptors.request.use(function(config){
let token = localStorage.getItem('token')
if(token) {
config.headers.Authorization = `Bearer ${token}`
}
return config;
})
export default axios
複製代碼
config.jsmongodb
module.exports = {
'DB_URL': 'mongodb://localhost:27017/jwt',
'secret': 'jeffywin'//祕鑰 加鹽
}
複製代碼
前臺界面vue-cli腳手架,沒什麼說的,登陸界面vue-cli
<template>
<div class="main">
<div class="item">
<div style="width:100px">登陸頁</div>
<input type='text' v-model='user.username'/>
</div>
<div class="item">
<div style="width:100px">密碼</div>
<input type='text' v-model='user.password'/>
</div>
<button @click="login">提交</button>
</div>
</template>
<script>
import axios from '../../utils/axios'
export default {
data() {
return {
user: {
username: '',
password: ''
}
}
},
methods: {
login() {
axios.post('/login',this.user).then(res => {
localStorage.setItem('token', res.data.token)//登陸後存儲token
this.$router.push('/order')
})
}
}
}
</script>
<style scoped lang="scss">
.main {
margin: 0 auto;
width: 300px;
.item {
display: flex;
margin-bottom: 10px;
}
}
</style>
複製代碼
order界面數據庫
<template>
<div class="order">
<h1>This is an order page</h1>
{{username}}//若是登陸成功,跳轉order界面,拿到登陸的用戶
</div>
</template>
<script>
import axios from '../../utils/axios'
export default {
data() {
return {
username: ''
}
},
mounted() {
axios.get('/order').then(res => {
this.username = res.data.user.username
})
},
}
</script>
複製代碼
源碼在本人github github.com/jeffywin/jw…