npm install express-jwt
const expressJwt = require('express-jwt');
app.use(expressJwt({
secret: 'userLogin', // 签名的密钥
algorithms: ["HS256"] // 设置算法(官方文档上没有写这个,但是不配置的话会报错)
}).unless({
path: ['/login', '/register/create', '/register/upload'] // 不经过 Token 解析的路径
}))
npm install jsonwebtoken
// 引入jsonwebtoken
const jwt = require('jsonwebtoken')
// 在返回的时候使用jsonwebtoken返回一个token
// 一般是作为登录成功的返回值
req.session.regenerate(err => {
if (err) {
return res.json({ret_code: 2, ret_msg: '登录失败'});
}
// 注意默认情况 Token 必须以 Bearer+空格 开头
const token = 'Bearer ' + jwt.sign(
{
user_id: data[0].dataValues.user_id,
isLogin: true
},
'userLogin'
)
return res.send({
success: true,
token: token
})
}
// error handler
app.use(function (err, req, res, next) {
console.log(err)
// 根据错误信息判断是否是未登录直接访问
if (err.name === 'UnauthorizedError') {
// 可以根据自己的业务逻辑来处理
return res.status(401).send('没有权限');
}
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.send('error');
});
app.use((req, res, next) => {
// 由于express-jwt需要配合前台发送的cookie使用,所以要把Access-Control-Allow-Credentials设置为true
// 设置Access-Control-Allow-Credentials为true后,Access-Control-Allow-Origin不能使用通配符,所以我改成req.get("origin")
// 允许的请求主机名及端口号 也可以用通配符*, 表示允许所有主机请求
res.setHeader('Access-Control-Allow-Origin', req.get("origin"));
// 允许请求携带cookie
res.setHeader('Access-Control-Allow-Credentials', true);
// 允许的请求方式
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// 允许的请求头 express-jwt的cookie是使用Authorization所以需要允许Authorization通过
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
res.setHeader('Access-Control-Expose-Headers', 'Authorization')
next();
});
express-jwt需要前端发送一段头部信息,才可以进行验证,所以前端需要对后台发送的token进行保存,在每次请求之前将token添加到头部中
// 设置cookie
export function setCookie(name, value, iDay) {
/*当时间参数存在的时候*/
if (iDay) {
/*设置过期时间*/
var oDate = new Date();
oDate.setDate(oDate.getDate() + iDay);
document.cookie = name + '=' + value + ';expires=' + oDate;
} else {
/*否者默认浏览器关闭过期*/
document.cookie = name + '=' + value;
}
}
// 获取cookie
export function getCookie(name) {
/*将获取到的字符串变成数组纯在arr中*/
/*得到的数据格式是这样的a=11; b=12*/
var arr = document.cookie.split('; ');
for (var i = 0; i < arr.length; i++) {
/*再拆分一次*/
var arr2 = arr[i].split('=');
//判断arr2[0]是否是要读取的Cookie
if (arr2[0] === name) {
return arr2[1];
}
}
return '';
}
import axios from 'axios'
import { getCookie } from './cookie'
import router from '../router'
import {MessageBox} from 'element-ui'
export function request(config) {
const ins = axios.create({
baseURL: 'http://127.0.0.1:3000',
withCredentials: true, // 这个必须设置,不然无法跨域传递信息
// crossDomain: true
})
// request拦截器 之后每个请求都会先查找token,如果token存在则会带上一个token
ins.interceptors.request.use(response => {
let token = getCookie('userLogin'); //获取Cookie
if (token) {
// 将cookie保存到头部的Authorization中,必须是Authorization
response.headers['Authorization'] = token
}
axios.defaults.withCredentials = true
return response
}, error => {
return Promise.reject(error)
})
// response拦截器
ins.interceptors.response.use(response => {
return response.data
}, error => {
// 判断错误类型,如果是401则是没有权限,跳转到登录界面
if (error.response.status === 401) {
MessageBox('请先登录帐号', '提示', {
confirmButtonText: '确定',
type: 'warning'
}).then(() => {
router.push({
path: '/login'
})
});
}
return Promise.reject(error)
})
return ins(config)
}
import { request } from '../utils/request'
export function getUser() {
return request({
url: 'getUser',
method: 'get',
})
}
import { getUser } from '../api/index'
created() {
// 验证成功会获取所有用户信息,验证失败会跳转到登录页面
this.getUser()
},
至此,只要前台请求接口,后台都会根据头部信息进行验证,验证成功以后就可以访问接口,验证失败会返回错误信息,前台可以在拦截器的部分进行自己的一些逻辑操作