什么是Token
Token 是在服务端产生的,当客户端传来的用户名/密码验证通过时,就会在服务器端生成一个Token返回给客户端,这个Token中包含了用户信息、过期时间等信息。客户端接收到返回的token后将其保存,在有效时间内客户端向服务器端发送请求时只需要带上这个token即可,无需再带上用户名和密码。
express中进行Token认证
1.安装 jsonwebtoken
npm install jsonwebtoken --save
2. 在 public文件夹下新建 token.js 文件,用户token的生成与解析
//用于生成和解析token
var jwt = require('jsonwebtoken');
var signkey = 'mes_qdhd_mobile_xhykjyxgs';
exports.setToken = function(username,userid){
return new Promise((resolve,reject)=>{
const token = jwt.sign({
name:username,
_id:userid
},signkey,{ expiresIn:'1h' });
resolve(token);
})
}
exports.verToken = function(token){
return new Promise((resolve,reject)=>{
var info = jwt.verify(token.split(' ')[1],signkey);
resolve(info);
})
}
3. 在 app.js 中进行token的相关配置,这里有一点很关键,要配置有哪些路由是不需要认证的,比如说登录接口,在未登录前客户端是没有token的,token必须要通过登录获得,因此这个接口必须不能进行token认证。
var vertoken = require('./public/token')
// 解析token获取用户信息
app.use(function(req, res, next) {
var token = req.headers['authorization'];
if(token == undefined){
return next();
}else{
vertoken.verToken(token).then((data)=> {
req.data = data;
return next();
}).catch((error)=>{
return next();
})
}
});
//验证token是否过期并规定哪些路由不用验证
app.use(expressJwt({
secret: 'mes_qdhd_mobile_xhykjyxgs'
}).unless({
path: ['/login']//除了这个地址,其他的URL都需要验证
}));
//当token失效返回提示信息
app.use(function(err, req, res, next) {
if (err.status == 401) {
return res.status(401).send('token失效');
}
});
4. 编写登录接口
router.post('/login', function(req, res, next) {
var username = req.body.username;
var password = req.body.password;
//生成token
settoken.setToken(username,userid).then((data)=>{
res.json({ token: data });
})
});
5. 获取数据接口
当未在请求头中加入token时,是无法获取到数据的
我们在请求头中加入token认证信息,这里要注意一点,一定要使用 Bearer token的格式,即在token前面要加上Bearer。 如下所示:
再次发送请求,可以看到返回了我们想要的信息。但是这个token不是永久有效的,它具有有效期时间,过了有效期当然这个token也就作废了,需要重新登录获取新的token。
有的人按照上面的做法都是一样的,但是为什么还是无法得到数据呢。
这里有一点肯很容易被忽略,如果在express中设置了请求头信息中没有含有Authorization的话,后端是无法接收到token的。
app.all('*', (req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "content-type");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
这里需要把 Authorization加入到请求头中。
res.header("Access-Control-Allow-Headers", "content-type,Authorization");
与VUE对接
在VUE用使用axios请求,可以在axios的请求拦截器中配置token
//请求拦截器
instance.interceptors.request.use(
config => {
const token = store.state.token;
token && (config.headers.Authorization = 'Bearer ' + token);
return config;
},
error => Promise.error(error)
)
还可以对不同的状态码进行相应的处理,这里只举例几个
const toLogin = () => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}
const errorHandle = (status) => {
// 状态码判断
switch (status) {
// 401: 未登录状态,跳转登录页
case 401:
toLogin() //403 token过期,跳转登录页
break;
case 403:
// tip('登录过期,请重新登录');
localStorage.removeItem('token');
store.commit('loginSuccess', null);
setTimeout(() => {
toLogin();
}, 1000);
break;
// 404请求不存在
case 404:
console.log('请求资源不存在');
break;
// default:
}}
往期推荐