token
token简介:
token令牌 用来检验用户是否有权限访问相应的内容
本质是一段长长的字符串
如果用户没有登陆,后端接口就应该不允许用户请求内容列表。
JWT (json web token) 身份认证
对于前后端分类模式的开发,大多使用JWT(json web token)
进行身份认证。 当成功登陆之后,后端返回的一个凭据(就是一个长长的字符串),有了这个凭据之后,后续再发请求接口,就可以带上它,就样就可以访问那些“权限接口”
1.分析
前端:
- 登录成功后,保存
token
到localstorage
- 请求
/my/xxx
接口时,在请求头
中加入Authorization
字段,值为token
。
后端:
- 前端用户登录成功时, 后端登录接口
生成token
,并返回给前端 - 后端收到请求接口时先判断,如果客户端请求的接口是需要做检验的(需要登陆之后才能访问),则要去
验证token
的真伪
一、token
-前端登陆成功后 后端返回token
1. 后端创建token 步骤
在node.js中
使用第三方模块 jsonwebtoken
创建token字符串。
在登陆接口成功后 创建token
并返回前端
- 下载安装
npm i jsonwebtoken
- 加载模块
const jwt = require('jsonwebtoken');
- 调用
jwt.sign()
方法创建生成token
- 参数1:必填,对象形式;希望在token中保存的数据
- 参数2:必填,字符串形式;加密的钥匙;后续解密token的时候,还需要使用。
- 参数3:可选,对象形式;配置项,比如可以配置token的有效期
- 参数4:可选,函数形式;生成token之后的回调
- 生成的token前面,必须拼接
Bearer
这个字符串。
2. 参考代码
const jwt = require('jsonwebtoken');
// 用户登陆方法
app.post('/login', (req, res) => {
// 其它代码......
// 调用生成 token 的方法
const tokenStr = jwt.sign(
{name: 'xxx' }, //希望保存在token的数据
'xxx密钥xxx', //秘钥 解密token的时候还需使用
{ expiresIn: 20 } //token有效期 单位:秒
);
const token = 'Bearer ' + tokenStr //生成token 前面需要拼接Bearer 【Bearer 后面要有空格】
// 把 token 字符串响应给浏览器
res.send({ code: 200, msg: '登录成功', token })
})
二、token
-前端保存后端回传的token
1. 前端保存token步骤
- 在首页面
index.html
当中 - 通过
localStorage.setItem('token名',后端返回过来的token字段)
- 保存到本地存储当中 有效时间后端设置了
2. 参考代码
$.ajax({
url: 'http://localhost:3000/user/login',
method: 'POST',
data: {
userName: $('#userName').val().trim(),
userPwd: md5($('#userPwd').val().trim())
},
success: (res) => {
console.log('返回的结果是', res)
const {code} = res
if(code === 200) {
// 保存从后端传回的token
localStorage.setItem('token', res.token)
// 跳入主页
// window.location.href = './index.html'
} else if(code === 201) {
alert('用户名密码有误')
} else {
alert(res.msg)
}
}
})
三、token
-前端ajax请求有访问权限接口 携带token
1. 前端访问权限接口 操作步骤
- 前端发送ajax请求请求有访问权限的接口时 (示例使用jquery)
- 在请求头里面
headers
设置Authorization
值为本地存储中保存的token字段
2. 参考代码
// 1.2 面向接口编程,请求三要素
$.ajax({
method: 'GET',
url: 'http://127.0.0.1:3001/list',
// 按照规范请求头传递 Authorization
headers: {
+ Authorization: localStorage.getItem('token'),
},
data: {
// 按接口文档规定 传递对应参数
},
success: (res) => {
// ... 省略
})
}
四、token
-后端代码实现token认证
选择使用express-jwt 第三方模块
进行身份认证。从模块名可以看出,该模块是专门配合express
使用的。
1. 后端实现token认证 步骤
- 下载安装
npm i express-jwt
- 主文件中加载模块
const jwt = require('express-jwt');
- 使用
express-jwt
验证token
是否正确 - 错误处理 提示token错误
2.参考代码
1)中间件技术-验证token
const jwt = require('express-jwt');
// app.use(jwt().unless());
// jwt() 用于解析token,并将 token 中保存的数据 赋值给 req.user
// unless() 约定某个接口不需要身份认证
app.use(jwt({
secret: 'xxx密钥xxx', // 生成token时的 钥匙,必须统一
algorithms: ['HS256'] // 必填,加密算法,消息签名算法(还有RS256) 无需了解
}).unless({
path: ['/user/login', '/user/register'] // 除了这两个接口,其他都需要认证
}));
上述代码完成后,当一个接口请求到了服务器后,它会自动验证请求头中的 Authorization
字段了,并且会自动完成:
- 如果没有问题
- 将
token
中保存的 数据 赋值给req.user
next()
。
- 将
- 如果有问题,则抛出错误
next(错误信息
)。
2)中间件技术-处理错误
在所有的路由最后,加入错误处理中间件
,来提示token
方面的错误。
app.use((err, req, res, next) => {
if (err.name === 'UnauthorizedError') { // 未经授权的 错误
// res.status(401).send('invalid token...'); //无效的token
res.status(401).send({ status: 1, message: '身份认证失败!' });
}
});
3)前端统一处理401错误
在index.html中,统一处理401错误
$(document).ajaxError(function( event, request, settings ) {
if(request.status === 401) {
// alert(request.responseJSON.msg)
return (location.href = './login.html')
}
})
五、优化 (前端统一携带token)
统一设置Authorization
在jquery中 通过$.ajaxSetup
: 用来统一设置ajax的配置
$.ajaxSetup({
headers: {
Authorization: localStorage.getItem('token'),
}
})
随后发出的ajax就会携带token