JWTJSONWebToken(JWT)是一个开放标准(RFC7519),它定义了一种紧凑、自包含的方式来确保各方之间作为JSON对象传输信息的安全。此信息可以被验证和信任,因为它是经过数字签名的。本文只讲Koa2+jwt的使用,不了解JWT的请到这里)了解更多。如果要在koa环境下使用koa2+jwt,需要先有一个空的koa环境。搭建环境比较麻烦。我直接用koa启动。这是我使用koa+typescript搭建的空环境。如果经常用koa写小Demo,可以点个star,方便~安装koa-jwtkoa-jwt的主要作用是控制哪些路由需要jwt校验,哪些接口不需要校验:import*askoaJwtfrom'koa-jwt';//路由权限控制除了路径中的路径不需要验证token。其他必须是app.use(koaJwt({secret:'my_app_secret'}).unless({path:[/^\/login/,/^\/register/]}));上面的代码除了需要jwt验证的登录和注册接口外,其他的请求都是需要的。使用jsonwebtoken生成并校验token,执行npminstalljsonwebtoken安装jsonwebtoken相关代码:import*asjwtfrom'jsonwebtoken';constsecret='my_app_secret';constpayload={user_name:'Jack',id:3,email:'1234@gmail.com'};consttoken=jwt.sign(payload,secret,{expiresIn:'1h'});上面代码中通过jwt.sign生成token,参数含义:payload:carrier,一般以用户信息作为Carrier生成tokencret:秘钥,可以是字符串也可以是文件expiresIn:过期时间1h表示返回登录令牌一小时import*ascryptofrom'crypto';从“jsonwebtoken”导入*作为jwt;asynclogin(ctx){//从数据库中找到对应的用户constuser=awaituserRespository.findOne({where:{name:user.name}});//密码加密constpsdMd5=crypto.createHash('md5').update(user.password).digest('hex');//比较密码的md5值是否一致。如果一致则生成token返回给前端if(user.password===psdMd5){//生成tokentoken=jwt.sign(user,secret,{expiresIn:'1h'});//响应前端ctx.body={token}}}前端拦截器front-end拿到登录返回的token,可以存储到localStorage中,然后在后面的请求中,把token放到在请求头的Authorization中将其带到服务器。这里我们以axios请求为例。发送请求时,通过请求拦截器将token插入到header中://Requestinterceptoraxios.interceptors.request.use(function(config){//从localStorage中取出tokenconsttoken=localStorage.getItem('tokenName');//StufftokenintoAuthorizationconfig.headers.Authorization=`Bearer${token}`;returnconfig;},function(error){//处理请求错误returnPromise.reject(error);});服务器处理前端发送的Token。前端发送请求携带token。后端需要判断以下几点:token是否正确,token不合法则返回错误。如果token过期,刷新token或者返回401表示需要重新登录。关于以上两点,需要在后台写一个中间件来完成:app.use((ctx,next)=>{if(ctx.header&&ctx.header.authorization){constparts=ctx.header.authorization.split('');if(parts.length===2){//取出tokenconstscheme=parts[0];consttoken=parts[1];if(/^Bearer$/i.test(scheme)){try{//jwt.verify方法验证token是否有效jwt.verify(token,secret.sign,{complete:true});}catch(error){//token过期生成一个新的enconstnewToken=getToken(user);//将新的token放入Authorization中返回给前端ctx.res.setHeader('Authorization',newToken);}}}}returnnext().catch(err=>{if(err.status===401){ctx.status=401;ctx.body='受保护资源,使用授权标头获取访问权限\n';}else{抛出错误;}});});上面的中间件需要验证token的时候需要到这里。可以理解为拦截器。在这个拦截器中,可以判断token是否正确,是否过期,并进行相应的处理。后端刷新令牌。前端需要更新令牌。还需要获取新的token,这样请求才不会报错。由于后端更新的token在响应头中,前端需要在响应拦截器中获取新的token。还是以axios为例://响应拦截器axios.interceptors.response.use(function(response){//获取更新后的tokenconst{authorization}=response.headers;//如果token存在,则有localStorage授权&&localStorage.setItem('tokenName',authorization);returnresponse;},function(error){if(error.response){const{status}=error.response;//如果是401或405,则转到登录页面if(status==401||status==405){history.push('/login');}}returnPromise.reject(error);});
