请问昨天结束的工作今天是不是已经堆起来了?今天来个加班班更新博客,看能不能给大家推荐一下,看在坚持的份上。有好消息也有坏消息。先说坏消息吧。学成这样,急需糖水复习一下以前的知识。这几天学的太快了,感觉有点急功近利,好消息是今天的内容是最终节点的基础内容。果然,天空不会让我失望。整个过程走完之后,就会有两个大案子,我昂着头走进了vue,等等,你学完这个就可以进去了。1、今天的第一个内容是讲web开发模型。今天主要讲的就是身份认证的内容。我们的网络开发模型分为两种类型。一种是服务端渲染方式,就是通过服务端进行字符串拼接,拼接出html页面,然后直接返回给客户端,这样就不需要我们的ajax了,直接给客户端就行了。他的优点是前端花的时间少。前端怎么了,也有利于SEO优化。它的缺点是占用服务器资源,不利于前后端分离,开发效率低。第二种模式:前后端分离模式,是一种依赖ajax的广泛应用。后端负责写API接口,前端负责调用接口就完事了。它的优点之一就是开发体验好。毕竟前后端分离,用户体验好,同时也减轻了服务器的压力。但缺点是不利于SEO优化。2然后我们进入身份认证,什么身份认证?通过一定的手段确认用户身份的一种方式。session认证用于服务端渲染开发,jwt认证用于我们的前后端分离。两者各有优势,谁也不会放过对方。3.先说session。我们先来了解一下http的无状态,就是说客户端的每一个http请求都是独立的。连续多次请求之间没有直接关系,服务器不会主动保存每个http请求的状态。(就像收银员一样,他能记住每一个来的顾客都是会员吗?)突破无状态限制。超市突破这个限制的办法就是给每个会员发会员卡吧?在我们的web领域,这种方式就是cookies。Cookie是存储在用户浏览器中的一个不超过4kb的字符串,由名称、值和有效期组成。安全性,适用范围的可选属性。在不同的域名下,我们的cookies是独立的。每当客户端发起请求时,会自动将当前域名下的所有cookies发送给服务器端。注意,它只是在当前域名下。他的特点是:自动发送,独立域名,过期时间限制,4kb限制3.1cookie在认证中的作用当我们的客户端第一次请求服务器时,服务器会通过响应头给客户端发送一个认证cookie,我们的浏览器会保存这个cookie,当我们下次请求时,它会直接发送这个cookie,也就是上面说的自动发送,可以证明我们的身份。请注意,我们的cookie并不安全。浏览器也提供了读写cookies的API,所以cookies很容易被伪造,就像我们的会员卡也是被伪造的一样。所以不要用cookies来存储重要数据,包括我们的jwt,后面会提到。3.2那么有没有办法提高我们cookies的安全性呢?那就是session认证,就像我们的会员卡?刷卡机制一样,可以去假卡。Session认证机制:首先我们的客户端登录账号密码发送登录请求,服务器端会开始验证。当验证成功后,会保存在服务器的内存中,并通过响应头返回一个对应的cookie字符串。我们浏览器会将这个字符串保存在当前域名下。当我们再次请求时,会将该域名下的所有cookies一起发送给服务器,服务器会找到对应的cookie匹配成功,找到您的信息。可以,然后认证成功3.3说了这么多,如何在服务器端使用我们的sesson,先安装导入两个步骤然后需要配置。注意configuration是固定的写法,secret可以是任意字符串。配置好之后就可以使用req.session来访问session对象,用sessin存储我们的一些数据,然后登录成功后可以通过session取回,我们注销的时候就可以了。destroy方法清除会话。请注意,它只会清除帐户信息,不会清除其他人的信息。具体代码如下:注意todo是我们需要做的//importexpressmoduleconstexpress=require('express')//创建expressconstapp=express()//TODO_01:PleaseconfiguretheSessionmiddlewareconstsession=require('express-session')app.use(session({secret:'mySession',resave:'false',saveUninitialized:'ture'}))//托管静态页面app.use(express.static('./pages'))//解析POST提交的表单数据app.use(express.urlencoded({extended:false}))//登录API接口app.post('/api/login',(req,res)=>{//判断用户提交的登录信息是否正确if(req.body.username!=='admin'||req.body.password!=='000000'){returnres.send({status:1,msg:'loginfailed'})}//TODO_02:Session登录成功后请保存用户信息//注意req.session对象只有在req.session上面配置session时才能使用.user=req.body//用户信息req.session.islogin=true//用户登录状态res.send({status:0,msg:'登录成功'})})//获取用户名的接口app.get('/api/username',(req,res)=>{//TODO_03:请从Session获取用户名,响应客户端//判断是否登录成功if(!req.session.islogin){关于turnres.send({status:1,msg:'fail'})}//如果登录成功,响应数据返回res.send({status:0,msg:'success',username:[req.session.user.username]})})//注销接口app.post('/api/logout',(req,res)=>{//TODO_04:清除Session信息req.session.destroy()res.send({status:0,msg:'Logoutsuccessful'})})//调用app.listen方法,指定端口号,启动webserverapp.listen(80,function(){console.log('Expressserverrunningathttp://127.0.0.1:80')})3.这个是session,然后我们看到下一个认证机制jwt,session需要cookie来实现,但是我们的cookie有个致命的问题,它没有支持跨域,如果涉及到跨域,需要配置很多步骤JWT是目前最流行的跨域认证方案。实现原理:首先客户端发起请求头发送账号密码,服务端校验。验证成功后,会加密一个token字符串,然后返回一个token字符串给您。我们获取到的token字符串会保存在localstorage或者sessionStorage中,当我们再次请求的时候,我们会通过一个授权请求头把token发送给服务器,服务器在获取到token的时候会把token还原到用户的信息对象中token,则身份认证成功。JWT的组件由三部分组成:header。负载。签名,这个这只是一个除法函数。我们的真实信息集中在有效载荷的中间。payload前后两个只是为了保证token的安全。如何在express中使用我们的token?需要安装两个包,还需要自己定义key。第四步,在sign方法中生成JWT字符串。该配置的有效期为指定期限内token可用于验证的期限;第五。在第一步jwt转json的语句中,unless语句表示配置了不需要认证的接口。第五步转换成json文件后,我们就可以使用req.user来获取信息了,而这个信息就是我们前四步将what转换为jwt字符串信息,最后当我们的token过期或者不合法的时候,就会报错发生。这个时候需要一个错误中间件//导入express模块??constexpress=require('express')//创建express的服务端实例constapp=express()//TODO_01:安装导入JWT相关的两个包,即jsonwebtoken和express-jwtconstjwt=require('jsonwebtoken')constexpressJwt=require('express-jwt')//允许跨域资源共享constcors=require('cors')app.use(cors())//解析post表单数据的中间件constbodyParser=require('body-parser')const{UnauthorizedError}=require('express-jwt')const{response}=require('express')app.use(bodyParser.urlencoded({extended:false}))//TODO_02:定义秘钥,建议将秘钥命名为secretKeyconstsecretKey='hardhardstudydaydayup'//TODO_04:注册解析和恢复的中间件appJWT字符串转JSONobjects.use(expressJwt({secret:secretKey,algorithms:['HS256']}).unless({path:[/^\/api\//]}))//登录界面app.post('/api/login',function(req,res){//将req.body中的数据传递给userinfo常量constuserinfo=req.body//登录失败if(userinfo.username!=='admin'||userinfo.password!=='000000'){returnres.send({status:400,message:'Loginfailed!'})}//登录成功//TODO_03:Loginsucceeded之后调用jwt.sign()方法生成JWT字符串并通过token属性发送给客户端//转换成token加密文件consttokenStr=jwt.sign({username:userinfo.username,algorithms:['HS256']},secretKey,{expiresIn:'1h'})水库。send({status:200,message:'登录成功!',token:tokenStr//发送给客户端的token字符串})})//这是一个授权的API接口app.get('/admin/getinfo',function(req,res){//TODO_05:使用req.user获取用户信息,使用data属性向客户端发送用户信息res.send({status:200,message:'获取用户信息successful!',data:{username:req.user}//要发送给客户端的用户信息})})//TODO_06:使用全局错误处理中间件捕获JWT解析失败后产生的错误app.use((err,req,res,next)=>{if(err.name==='UnauthorizedError'){//这个错误是token解析失败导致的returnres.send({status:401,msg:'invalidtoken'})}else{//其他错误returnres.send({status:500,msg:'unknownerror'})}})//调用app.listen方法,指定端口号并启动web服务器app.listen(8888,function(){console.log('Expressserverrunningathttp://127.0.0.1:8888')})然后后面会有两个项目,将之前学过的节点进行整合。到时候单独开个blog说一下,还有一些需要注意的地方
