jwt是jsonwebtoken的缩写。本文介绍其原理。最后,后端使用nodejs实现了如何为客户端生成token令牌和验证token。为什么我们需要会话管理?我们在使用nodejs作为前端或者其他服务提供resful接口的时候,http协议是一个无状态的协议。有时我们需要根据请求的上下文获取具体用户是否有权限,对用户的上下文进行操作。所以,cookiessession、jwt技术的出现,都是对HTTP协议的补充。它允许我们用HTTP协议+状态管理构建一个面向用户的WEB应用。2.session和cookiessession和cookies相关,session是服务端在客户端cookies中植入的session_id,服务端保存了session_id对应的当前用户的所有状态信息。客户端每次向服务器请求时,都会带上cookies中的session_id,服务器会判断是否有具体的用户信息,如果没有则调整登录。cookies的安全性不好。攻击者可以获取本地cookies进行欺骗或利用cookies进行CSRF攻击。当cookies在多个域名下时,就会出现跨域问题。会话信息存储在服务器上。我们在stke中多机部署node.js时,需要解决共享session,导致session持久化的问题。所以session不支持分布式架构,不能支持横向扩展。它只能通过数据库保存session数据以供共享。如果持久层失败,则会发生身份验证失败。3.jwt的定义jwt是jsonwebtoken的全称。它解决了上述会话的问题。优点是服务器不保存任何会话数据,即服务器变得无状态,更容易扩展。什么情况下适合使用jwt,我觉得是授权的场景,因为jwt简单易用,开销小,后端无状态,所以被广泛使用。4.jwt的原理JWT的原理是在服务端通过认证后,生成一个JSON对象返回给用户,如下图。{"Name":"张三","Role":"Administrator","ExpirationTime":"July1,20180:00"}之后,用户与服务器通信时,必须发回这个JSON目的。服务器完全依赖这个对象来识别用户。为了防止用户篡改数据,服务端在生成这个对象的时候会加上一个签名。5、JWT认证流程流程说明:浏览器发起登录请求,携带用户名和密码;服务器根据用户名和明码验证身份到数据库,根据算法将用户标识打包生成token,服务器返回JWT信息给浏览器。JWT不应该包含敏感信息,这一点非常重要。浏览器发起获取用户信息的请求,将刚刚获取到的token发送给服务器,一般在header中,字段为authorization。服务器发现数据中有token,对token信息进行解码,然后重新签名验证真伪;服务器返回用户的用户信息;服务器可以在payload中设置过期时间,如果过期,客户端可以重新发起验证。6.jwt数据结构jwt包含三部分使用样式Header{"alg":"HS256","typ":"JWT"}//algorithm=>HMACSHA256//type=>JWT这个是固定的方式写作。alg表面使用HS256算法Payloadload,load,JWT指定7个官方字段iss(issuer):issuerexp(expirationtime):过期时间sub(subject):subjectaud(audience):Audiencenbf(NotBefore):Effectivetimeiat(IssuedAt):发行时间jti(JWTID):Number除了这七个,还可以自定义,比如过期时间。SignatureSignature对header和payload的前两部分进行签名,防止数据篡改HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)secret是一个字符串,保存在后端,需要注意的是JWT用作令牌(token),在某些场合可能会放在URL中(比如api.example.com/?token=xxx)。base64有+、/、=三个字符,在URL中有特殊含义,所以必须替换:=省略,+替换为-,/替换为_。这就是Base64URL算法。7.如何使用jwt在HTTP请求的头信息Authorization字段中,Bearer也是规定的Authorization:Bearer通过url传输(不推荐)http://www.xxx.com/pwa?token=xxxxx如果是post请求也可以放在请求体中8.在koa项目中可以使用现成的库,jwt-simple或者jsonwebtokenletkoa=require('koa');letRouter=require('koa-router');letbodyparser=require('koa-bodyparser');letjwt=require('jwt-simple');letrouter=newRouter()letapp=newKoa();app.use(bodyparser());//可以自定义letsecret;//验证是否登录router.post('/login',async(ctx)=>{let{username,password}=ctx.request.body;if(username==='admin'&&password==='admin'){//平时查数据库,这里简单演示一下lettoken=jwt.encode(username,secret);ctx.body={code:200,username,token,}}});//验证是否有权限router.get('/validate',async(ctx)=>{letAuthorization=ctx.get('authorization')let[,token]=Authorization。分裂('');if(token){try{letr=jwt.decode(token,secret);ctx.body={code:200,username:r,token}}catch(e){ctx.body={code:401,data:'未登录'}}}else{ctx.body={code:401,data:'未登录'}}});app.use(router.routes());app.listen(4000);实现两个接口,一个是/login,验证是否登录,一个是validate,验证是否有权限请求。当前用户存在。如果它存在,它将签署用户名。请勿将密码等敏感信息带入签名。客户端收到后端给token的token,然后请求其他接口,比如本例中的/validate,ajax请求的时候可以在header中指定authorization字段,后端拿到token进行解码,然后进行签名header和payload,如果前后签名一致,说明没有被篡改,权限校验通过,因为是同步过程,可以用trycatch来捕获错误。可以使用nodejs自带的加密模块crypto生成base64字符串。需要注意的是,生成base64需要替换+-=,=省略,+替换为-,/替换为_。这就是Base64URL算法。token令牌的组成是header、payload和sigin的通道。解码形成base64urlUlscape是固定的写法,解码base64的内容base64');returnthis.base64urlEscape(r)},base64urlEscape(str){返回str.replace(/\+/g,'-').replace(/\//g,'_').replace(/=/g,'');},toBase64(content){returnthis.base64urlEscape(Buffer.from(JSON.stringify(content)).toString('base64'))},encode(username,secret){letheader=this.toBase64({typ:'JWT',alg:'HS256'});让content=this.toBase64(username);letsign=this.sign([header,content].join('.'),secret);返回[header,content,sign].join('.')},base64urlUlscape(str){str+=newArray(5-str.length%4).join('=');返回str.replace(/\-/g,'+').replace(/_/g,'/');},decode(token,secret){让[header,content,sign]=token.分裂('。');让newSign=this.sign([header,content].join('.'),secret);if(sign===newSign){returnBuffer.from(this.base64urlUlunescape(content),'base64').toString();}else{thrownewError('tampered')}}}10.jwt的优缺点JWT默认是不加密的,但是可以加密的。生成原始令牌后,可以使用修改后的令牌再次加密。当JWT不加密时,一些隐私数据无法通过JWT传输。JWT不仅可以用于身份验证,还可以用于信息交换。善用JWT有助于减少服务器对数据库的请求次数。JWT最大的缺点是服务端不保存session状态,所以在使用过程中无法取消token或者改变token的权限。也就是说,JWT一旦发出,在有效期内一直有效。JWT本身包含认证信息,如果信息泄露,任何人都可以获得token的所有权限。为了减少盗用,JWT的有效期不要设置的太长。对于一些重要的操作,用户每次使用都应该进行身份验证。为了减少盗用和盗用,JWT不推荐使用HTTP协议传输代码,而是使用加密的HTTPS协议进行传输。