当前位置: 首页 > 科技观察

使用NodeJS实现JWT(jsonwebtoken)的原理

时间:2023-03-13 14:24:45 科技观察

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":"0:00onJuly1,2018"}之后,用户与服务器通信时,必须发回这个JSON目的。服务器完全依赖这个对象来识别用户。为了防止用户篡改数据,服务端在生成这个对象的时候会加上一个签名。五。JWT认证流程JWT流程描述:浏览器发起登录请求,携带用户名和密码;服务器根据用户名和明码验证身份到数据库,根据算法将用户标识打包生成token,服务器返回JWT信息给浏览器浏览器,JWT不应包含敏感信息,这是非常重要的。浏览器发起获取用户信息的请求,将刚刚获取到的token发送给服务器,一般在header中,字段为authorization。服务器发现数据中有令牌。解码token信息,然后再次签名验证身份;服务器返回用户的用户信息;服务器可以在payload中设置过期时间,如果过期,客户端可以重新发起验证。6.JWT数据结构JWT使用style包含三个部分,分别是header(头部)、Payload(负载)和Signature(签名)Headerheader{"alg":"HS256","typ":"JWT"}//algorithm=>HMACSHA256//type=>JWT这个是固定的写法,alg面使用HS256算法Payload加载,加载JWT规定的7个官方字段iss(issuer):issuerexp(expirationtime):expirationtimesub(subject):subjectaud(audience):audiencenbf(NotBefore):effectivetimeiat(IssuedAt):issuedtimejti(JWTID):number除了这七个,还可以自定义,比如过期时间Signaturesignature对前两部分header签名和payload防止数据篡改HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)secret是一个字符串,保存在后端,需要注意的是JWT作为token令牌,可能是在某些情况下放置在URL中(例如api.example.com/?token=xxx)。base64有+、/、=三个字符,在URL中有特殊含义,所以必须替换:=省略,+替换为-,/替换为_。这就是Base64URL算法。七。jwt的使用方法在HTTP请求的头信息Authorization字段中,Bearer也是指定的Authorization:Bearer通过url传输(不推荐)http://www.xxx.com/pwa?token=xxxxx如果是post请求也可以放在requestbody中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='zhenglei';//验证是否登录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.split('');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.路由());app.listen(4000);实现两个接口,一个是/login,验证是否登录,一个是validate,验证是否有权限。如果它存在,它将被签名为用户名。请勿将密码等敏感信息带入签名。客户端收到后端给的token令牌,然后请求其他接口。比如本例中的/validate,当ajax请求时,可以在header中指定authorization字段,在后端拿到token解码,然后再对header和payload进行签名。如果前后签名一致,说明没有被篡改,权限验证通过,因为是同步过程,所以可以用trycatch来捕获错误9.sha256hash的实现原理算法,可以使用nodejs自带的加密模块crypto生成base64字符串。需要注意的是,生成base64需要替换+-=,=省略,+替换成-,/替换成_。这就是Base64URL算法。token令牌的组成是header、payload和sigin的通道。解码形成base64urlUnescape是固定的写法,base64的解码内容);returnthis.base64urlEscape(r)},base64urlEscape(str){returnstr.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'});letcontent=this.toBase64(username);letsign=this.sign([header,content].join('.'),secret);return[header,content,sign].join('.')},base64urlUnescape(str){str+=newArray(5-str.length%4).join('=');returnstr.replace(/\-/g,'+').replace(/_/g,'/');},decode(token,secret){let[header,content,sign]=token.split('.');letnewSign=this.sign([header,content].join('.'),secret);if(sign===newSign){returnBuffer.from(this.base64urlUlunescape(content),'base64').toString();}else{thrownewError('已转改')}}}10.JWT的优缺点JWT默认是不加密的,但是可以加密生成原始token,用修改后的token再次加密。当JWT不加密时,一些隐私数据无法通过JWT传输。JWT不仅可以用于身份验证,还可以用于信息交换。善用JWT有助于减少服务器对数据库的请求次数。JWT最大的缺点是服务端不保存session状态,所以在使用过程中无法取消token或者改变token的权限。也就是说,JWT一旦发出,在有效期内一直有效。JWT本身包含认证信息,一旦信息泄露,任何人都可以获得token的所有权限。为了减少盗用,JWT的有效期不要设置的太长。对于一些重要的操作,用户每次使用都应该进行身份验证。为了减少盗用和盗用,JWT不推荐使用HTTP协议传输代码,而是使用加密的HTTPS协议进行传输。