当前位置: 首页 > 后端技术 > Node.js

NodeJS(ExpressFramework)实现Token验证免密码登录(一)

时间:2023-04-03 21:00:58 Node.js

阅读文章前,强烈建议先把项目拉下来!案例来自弟弟的开源项目“ProjectGithub”。文章内容只是个人学习的一些总结经验,不具有权威性。这是Node服务器的实现,后面会写前端的实现。什么是Token验证常见的Token验证方式:OAuth2,比如:微信授权登录(貌似也属于Token验证)是基于JWTToken验证的,在KiteBlog中使用。推荐阅读:JWT超详解,说说几种常用的登录认证方式,你用的是哪一种?什么是JWT(JSON网络令牌)?推荐阅读:JSONWebToken入门教程JSONWebToken-在Web应用程序之间安全传输信息在NodeJS中实现令牌的生成和验证(Express)安装jsonwebtoken和express-jwt首先我们先安装jsonwebtoken和express-jwt这两个中间件组件jsonwebtoken:用于生成Token。它还具有解析Token的功能express-jwt:用于解析Token(比jsonwebtoken方便),将解析后的数据存储在requset.user#安装jsonwebtokennpmijsonwebtoken#安装express-jwtnpmiexpress-jwt生成token如果你阅读上面关于JWT的文章,大家会知道JWT是由三部分组成的,分别是Payload、Header、Signature。jsonwebtoken为我们提供了sign(payload,secretOrPrivateKey,[options,callback])方法。sign方法对应JWT签名(Signature)actionpayload:payload,参数类型:objectsecretOrPrivateKey:自定义密钥,为敏感信息。参数类型:字符串选项:可以配置header、payload,指定算法类型。参数类型:对象callback:Callback眼尖的应该会发现参数payload和options都是可以配置的。这里有例子。根据自己的习惯选择即可。Payload的JWT部分指定了7个官方字段,都是可选的。可以以对象的形式直接传递给payload参数。iss(issuer):发行者exp(expirationtime):过期时间sub(subject):主题aud(audience):受众nbf(NotBefore):生效时间iat(IssuedAt):发行时间jti(JWTID):序号以上七个字段在复制代码选项中也可以接受,只是字段名称不同。iss----issuerexp----expiresInsub----subjectaud----audiennbf----notBeforeiat----noTimestampjti----jwtid复制代码之后options提供algorithm和header,对应的使用的加密算法和JWT的Header部分,其实算法也应该属于Header部分。说了这么多,其实我们一般只会用到exp(expiresIn)和algorithm这两个字段。例1:token的有效时间在option中配置//首先引入jsonwebtokenvarjsonWebToken=require('jsonwebtoken');//key,当然实际项目中的key应该是不正常的。constSECRET_KEY='kite1874'consttoken=jsonWebToken.sign({//Payload部分,这里省略官方的七个字段,可以携带一些可以识别用户的信息。例如userId。//不要使用敏感信息,比如密码,Payload就可以解析出来。userId:user.userIdrole:user.role},SECRET_KEY,{expiresIn:"24h",//token有效期//expiresIn:60*60*24*7,两种写法//algorithm:"HS256"是默认使用“HS256”算法})console.log(token)复制代码例子2:我们也可以在payload中配置有效时间consttoken=jsonWebToken.sign({//exp的值是一个时间戳,这里是表示token会在1h后过期exp:Math.floor(Date.now()/1000)+(60*60)userId:user.userIdrole:user.role},SECRET_KEY)复制代码jsonwebtoken除了生成token,它还提供了一种解析和验证token的方法,jwt。验证(令牌,secretOrPublicKey,[选项,回调])。这里不做演示,有兴趣的朋友可以参考文档:《JsonWebToken》验证tokenexpress-jwt是为express框架开发的JWTToken验证中间件。下面简单说一下它的用法。主要有两种方法。一是对所有需要验证的请求都加上验证;另一种是先对所有请求添加校验,然后为不需要校验的请求配置白名单。方法一:varexpress=require('express');varjwt=require('express-jwt');varapp=express();//Secret_key要和生成的Token一致constSECRET_KEY='kite1874'//secret是key,algorithms是算法。需要注意的是,如果在生成Token的时候没有手动设置算法//默认是使用HS256进行加密。“express-jwt6.0”版本要加algorithm:['HS256'],哭死我了!app.get("/test",jwt({secret:SECRET_KEY,algorithms:['HS256']}),function(req,res){//dosomething...})看完上面的例子,显然,它不符合我们的最后期限。一个普通的项目有几十个API需要几分钟。我们不可能一一添加验证方式://注册中间件,相当于配置一个全局的token验证,除非是上面说的白名单//把不需要token验证的请求填入路径,支持数组,字符串,常规app.use(jwt({secret:SECRET_KEY,algorithms:['HS256']}).unless({path:['/auth/adminLogin',/^\/public\/.*/]}));///auth/adminLoginapi和public文件不需要token验证。这种复制代码的方式是不是更方便、更漂亮、更容易维护呢?Token解析出的用户信息,默认存储在req.user中,可以直接使用req.user.userId来使用生成Token时填写的用户id。您还可以通过requestProperty和resultProperty来设置存储用户信息的对象。这里就不展开了。详细文档请参考:express-jwt验证错误处理。您可以使用app.use()注册并处理验证失败的情况。app.use(function(err,req,res,next){if(err.name==='UnauthorizedError'){res.status(401).send("你在做什么?你想闯入?!")}})复制代码注意(个人理解,不权威)这里的Token生成,验证,检查都是在没有错误处理的情况下完成的。token的生成一般在登录后生成,返回给前端。前端获取Token,并在每次请求API时携带Token。Token相当于用户的身份,不能轻易泄露。Token一旦发行,不能主动作废。有效期届满后方可作废。也就是说,即使你改了密码,之前的Token还是有效的。可以修改后台生成Token时使用的key,防止之前的Token验证通过,但这意味着之前生成的Token全部失效,无法让某个用户退出。这显然是不合适的。因此,当用户修改密码时,前端一般会清除之前保存的Token,然后获取新的Token。有的朋友可能会想到把Token存放在后端,每个用户对应一个token。在修改账号的时候,生成一个新的Token来覆盖之前的Token,但是这样就违背了使用Token的目的,主要是为了减轻服务器的压力。在客户端而不是服务器上存储尽可能多的信息。使用Token可以防御CSRF攻击。之前写过一篇关于网络安全的文章。感兴趣的朋友可以阅读《XSS攻击、CSRF攻击、SQL注入、流量劫持(DNS劫持、HTTP劫持)——浏览器安全》