在例如身份验证场景中,用户一旦登陆,接下来的每一个请求都会包含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…