JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。
架构图:
特点:
- JWT默认不加密,但可以加密。生成原始令牌后,可以使用改令牌再次对其进行加密。
- 当JWT未加密方法是,一些私密数据无法通过JWT传输。
- JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
配合express使用
1、安装依赖
- jsonwebtoken(用户签名和验证):https://www.npmjs.com/package...
- express-jwt(对jsonwebtoken的封装,能够更好的搭配express):https://www.npmjs.com/package...
> npm install jsonwebtoken express-jwt -S
2、服务端生成token
var jwt = require('jsonwebtoken');
// 生成token
function generateToken() {
return jwt.sign({
foo: 'bar',
}, 'hahaha', {
expiresIn: '1d' // 1天 https://github.com/zeit/ms
});
}
如登录完成后返回给前端
router.post('/xxx/login', function(req, res, next) {
res.json({
status: true,
data: {
token: generateToken()
},
message: '登录成功!'
});
});
前端传输token
拿到服务端返回的token后,这里要存储起来,然后在需要验证的接口上添加token,传输给服务端,headers传输示例如下:
$.ajax({
headers: {
token: localStorage.getItem('token') // 通过headers传输token到服务端
},
// ...
});
服务端路由拦截
var jwt = require('jsonwebtoken');
router.use(function(req, res, next) {
if(req.headers.hasOwnProperty('token')) {
jwt.verify(req.headers.token, 'hahaha', function(err, decoded) {
if(err) {
res.json({
status: false,
message: 'token不存在或已过期'
});
} else {
next();
}
});
} else {
next();
}
});
上面代码是纯使用jsonwebtoken方式处理的,从生成传输到验证一条龙。
那么express-jwt是如何使用的呢?
整体流程:
服务端生成方式不变,不过前端的传输方式变成这样了,这里不再是token了,而是约定好的authorization了
$.ajax({
headers: {
authorization: 'Bearer ' + localStorage.getItem('token') // "Bearer "这个也是约定的,必须是这样的格式
},
// ...
});
服务端使用
router.post('/xxx', expressJWT({secret: 'hahaha'}), function (req, res, next) {
// ...
});
前端验证
$.ajaxSetup({
complete: function (res) { // 接口请求完成拦截
// 验证token,不存在 重新获取或退出登录
}
});
整体步骤不多,由于是封装好的,使用起来也比较方便。
JWT缺点:
- JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。
- JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。