前言
我们在写项目的时候,会有一些功能是基本共有的,比如说登录,而对于这一块的处理我们自然想到会使用token来进行鉴权的处理,那么今天我们就来解决一下这一块的内容
技术栈:
前端:vue3 +vuex+axios等
后端:koa2
首先获取token
当用户在第一次登录的时候,需要向服务器发送请求,并且携带输入的信息,比如用户的密码和用户名称,然后后台通过查询是否存在这个用户,如果该用户存在,那么就允许其登录,并且返回一个token
,这个token使用户的一些关键信息,比如说用户的名称
,当用户再一次打开页面的时候,请求数据可以携带token,这样后台通过解析token,然后使用其中的信息来对数据库进行查找。
具体如何获取token这里不再重复的赘述,之后我会专门再一篇文章来讲解登录的前端后端处理(获取token),这里主要讲解token的过期如何处理。
对请求的封装
我们要对token进行鉴权处理,每次在请求的时候都要在请求头携带token,在后台进行判断,看token是否i过期,如果过期了就需要给前端返回错误信心,然后前端就跳转到登录页面提示用户重新登录,那么我们就需要首先封装请求方法。
具体封装如下:
const service = axios.create({ baseURL: import.meta.env.VITE_APP_BASE_URL, timeout: 5000, });
service.interceptors.request.use((req) => { // 在请求中携带token,可以用来获取用户的信息数据 const token = store.getters.token; req.headers.Authorization = `Bearer ${token}` || ""; return req; });
对后端返回的数据进行处理,并且处理错误
service.interceptors.response.use( (res) => { const { code, msg, type } = res.data; // code代表的是错误码 if (code == "0") { if (type) ElMessage.success(msg); return res.data; } }, async (error) => { // 抛出错误 const { msg, code } = error.response.data; // 错误码为1003表示此时token过期,需要重新登录 if (code == "1003") { // 首先表明此时token过期,我们需要手动清除缓存中的token ElMessage.error(msg); //调用vuex中mutations中的方法来请除token store.commit("user/setToken", ""); //清除本地存储的token clearItem(); //跳转回登录页面 router.push("/login"); } } );
注意这里因为我们使用vuex来进行全局数据共享,因此这里我们要首先进行commit请求,全局共享的数据赋值为空,并且清除本地localstorage存储的的数据。在最后使页面跳转到登录页面
后端处理
我们知道在使用koa进行开发的最大的特点就是可以拆分中间件
,使后台代码书写逻辑更加的严谨,环环相扣
在进行其他的活动之前,我们首先需要对请求中的token进行鉴权判断此时token是否有异常
使用中间件进行判断,捕获错误,判断token是否正常。
在index.js文件中
const koajwt = require("koa-jwt"); const { VerifyTokenExpired } = require("../middleware/user.middleware"); app.use(VerifyTokenExpired); // 添加某些接口可以不进行校验 app.use(koajwt({ secret: Secretkey }).unless({ path: [/^/users/login/] }));
这里使用的中间件使koa提供的,需要传递我们当时生成token的时候定义的密钥,后面的unless指的是不需要进行鉴权的接口,比如登录接口就不需要进行鉴权,因为此时token还没有生成.
这就是我对token的过期处理,主要是在后台使用了一个koa中的中间件koa-jwt
我们可以在官网看到详细的使用方法。然后就是自己写了一个中间件进行错误的捕获操作。
npm i koa-jwt
之后我自定义了一个中间件来koajwt这个中间件的错误进行了捕获.,判断错误码是否为401(表明用户身份错误),如果得到了错误码,那么就直接进行处理,返回错误信息给前端.不在进行下一步的活动.
// 验证token是否过期,定义处理函数 const VerifyTokenExpired = async (ctx, next) => { await next().catch((err) => { if (err.status == "401") { return ctx.app.emit("error", UserTokenExpired, ctx); } else { throw err; } }); };
注意一点,这里我是用ctx.app.emit
,这样做的目的就是将所有错误都统一的进行处理,并且这个UserTokenExpired
是写好的错误信息,作为参数传递过去,来统一的进行处理.
![tutieshi_640x377_5s](C:\Users\29227\Desktop\tutieshi_640x377_5s.gif)module.exports = { UserTokenExpired: { code: "1003", msg: "登录过期,请重新登录", result: "", }, }
app.on("error", errHandler);
当然这个errHandler
也可以理解为一个中间件,这个中间件目的是统一的处理错误信息(修改错误码,返回前端错误信息等等).
module.exports = (err, ctx) => { //之前传递的错误信息可以在err中获取到 // 默认status是500 let status = 500; switch (err.code) { case "1001": status = 400; break; case "1002": status = 409; break; case "1003": status = 401; break; default: status = 500; break; } ctx.status = status; ctx.body = err; };
这样处理之后就可以交给前端了,然后前端就可以通过一些方式,比如使用element-plus来给用户进行提示,并且进行响应的操作.
然后如果token没有过期,我们就可以放行继续执行后续的路由,比如获取用户的数据,然后将数据最后返回给前端等等,这里由于不是本届主要讲的,因此不展开赘述.
效果示意图:
总结
这次给大家讲了一下我在项目中如何对token进行鉴权处理,这次还没有对token讲解完成,下次将登录和获取token方式讲解完成.让大家有一个更加清晰的认识,希望能对你有所帮助,后期我也会不断修改精进这篇文章.