NodeJS(二)

一.bcrypt模块

bcrypt模块对用户密码进行加密。

1.1介绍:

​ bcrypt算法相对来说是运算比较慢的算法,越慢的算法越安全。

bcrypt加密后的字符串形如: $2b$10$2UCl0qI6K7tgtFmcO.DzdOKmBxfQorIuUV8Hdb12go7sHJitOV9w.

其中:
$是分割符,无意义;
2b 是bcrypt加密版本号;
10是cost的值;而后的前22位是salt值;再然后的字符串就是密码的密文了.

1.2安装:

 npm   i   bcrypt   --save/-S

1.3加密代码:


//1、引入模块
let  bcrypt= require("bcrypt");

//2、 产生salt

let salt = bcrypt.genSaltSync(11); // 11 是迭代次数

//3、加密
// bcrypt.hashSync(用户注册时输入的密码,salt); 
let pass = bcrypt.hashSync("123456",salt); 

console.log("pass",pass);//pass就是加密后的结果,把这个可以存储到数据库中

// $2b$10$1MtFAztjfpDTm8z.PjQTwOo6k4FrRiXwbZKq0oAKWqWI94mhzJfTG
// $2b$11$jMC6xi32MVFDApY.valjJ.f7W5gGXQoLj3VZlrPQ8Fik.pVQ/szTK

查看用户输入密码和数据库中是否一致

// 验证密码是否正确
//1、引入模块
let  bcrypt= require("bcrypt");

// let isMatch = bcrypt.compareSync(用户登录时输入的密码,数据库中拿到的密码);

let isMatch = bcrypt.compareSync("123456","$2b$11$jMC6xi32MVFDApY.valjJ.f7W5gGXQoLj3VZlrPQ8Fik.pVQ/szTK");

console.log(isMatch);//true:表示密码一致;false:密码不一致

示例:bcrypt加密 注册和登录

二. 身份验证

​ HTTP 是一种没有状态的协议,也就是它并不知道是谁访问(或者说,没法区分,每次的访问和以前哪次的访问来自同一个客户端)。客户端用户名密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证

2.1session(会话)

2.1.1思想

​ 1、当用户打开浏览器,首次访问某个网站(服务器),服务器会产生一个唯一的编号(sessionId),在响应时,把该编号发给客户端,客户端把该编号存储在cookie里。

​ 2、当用户二次访问(如:点击超链)服务器,那么,请求时,会携带保存在cookie里的编号,服务器端拿到该编号后,会跟session中的编号进行对比,就能知道本次访问和哪次访问是同一个客户端。

2.1.2业务场景:

​ 1、客户端发送用户名和密码,请求登录

​ 2、服务端收到请求,去库验证用户名与密码

​ 3、验证成功后,服务端种一个cookie或发一个字符到客户端,同时服务器保留一份session

​ 4、客户端收到 响应 以后可以把收到的字符存到cookie

​ 5、客户端每次向服务端请求资源的cookie会自动携带

​ 6、服务端收到请求,然后去验证cookie和session,如果验证成功,就向客户端返回请求的库数据

Session存储位置: 服务器内存,磁盘,或者数据库里

Session存储内容: id,存储时间,用户名等

客户端携带 : cookie自动带

2.1.3express-session

1、引入session模块: var session = require(‘express-session’);
2、创建session中间件:

  app.use(session(options)); 

示例:

app.use(session({
	secret: 'recommend 128 bytes random string',
	cookie: { maxAge: 20 * 60 * 1000 },//session的过期时间(没有错,cookie和session息息相关,所以,是用cookie.maxAge来设置session的过期时间)
 	resave: true,
  	saveUninitialized: true
	})
);

​ 3、保存变量:

req.session.变量名= 值;

​ 4、获取变量:

req.session.变量名

示例:session 登录和其它需要验证身份的模块(如:添加,删除)

2.2token

现在比较流行。

2.2.1思想

在服务端不需要存储用户的登录记录,全部发给客户端**由客户端自己存(**cookie,localStorage)

​ 1、客户端使用用户名跟密码请求登录
​ 2、服务端收到请求,去验证用户名与密码

​ 3、验证成功后,服务端会签发一个 Token(加了密的字符串),再把这个 Token 发送给客户端
​ 4、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
​ 5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token(需要程序员写)
​ 6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

示例:vue项目(webserver)和nodejs项目(apiserver)使用token。

2.2.2实现

jsonwebtoken的安装引入

let jwt = require('jsonwebtoken')
2.2.3生成签名(token)
let token = jwt.sign(payload, secretOrPrivateKey, [options, callback])
2.2.4校验token
jwt.verify(token, secretOrPublicKey, [options, callback])
//token: 制作后的token
//secretOrPublicKey: 解密规则,字符串,或者公钥
//callback:: 回调 err 错误信息 decode 成功后的信息
//options: expiresIn 过期时间
2.2.5token删除

由客户端,负责删除,服务器端没有任何保存,所以,只需要在客户端删除就行。

示例:token 登录,其它需要验证身份的模块(如:添加,删除)

三.session vs token

sessiontoken
服务端保存用户信息×
避免CSRF攻击×
多服务器粘性问题存在不存在

多服务器粘性问题

当在应用中进行 session的读,写或者删除操作时,会有一个文件操作发生在操作系统的temp 文件夹下,至少在第一次时。假设有多台服务器并且 session 在第一台服务上创建。当你再次发送请求并且这个请求落在另一台服务器上,session 信息并不存在并且会获得一个“未认证”的响应。这时候,就需要把在第一台服务器上保存的session给其它服务器上也保存。然而,在基于 token 的认证中,这个问题很自然就被解决了。没有粘性 session 的问题,因为在每个发送到服务器的请求中这个请求的 token 都会被拦截

对于注销登录来说,token只需要在客户端删除就行。

四.如何保存信息给浏览器(cookie)

4.1、前端保存:

cookie/localstorage

4.2、后端操作cookie:

服务器给浏览器种cookie: cookie-parser

Cookie的创建(express会将其填入Response Header中的Set-Cookie):

格式:

4.2.1、添加cookie
res.cookie(name, value [, options]);
//参数:
   name: cookie名
   value: 类型为String和Object。
   Option: 类型为对象,可使用的属性如下:
   domain:cookie在什么域名下有效,类型为String,。默认为网站域名
   expires: cookie过期时间,类型为Date。如果没有设置或者设置为0,那么该cookie只在这个session有效
   maxAge: 实现expires的功能,设置cookie过期的时间,类型为String,指明从现在开始,多少毫秒以后,cookie到期。
   path: cookie在什么路径下有效,默认为'/',类型为String
   secure:只能被HTTPS使用,类型Boolean,默认为false 
4. 2.2、删除cookie
res.clearCookie(name [, options]);
4.2.3、获取cookie
req.cookies.键名  //cookie是在客户端保存,每次请求时会携带,所以,用req对象获取cookie

示例:

设置键为name,值为:baobao,可访问的域名为:.example.com,可访问的路径:/admin',只可以用https访问
res.cookie('name', 'baobao', { 
				domain: '.example.com', 
					maxAge:10000*1000,
				path: '/admin', 
				secure: true 
				});

cookie的value为对象
res.cookie('cart', { items: [1,2,3] });

服务器给浏览器种cookie的同时在服务器上生成session: cookie-session

五.文件上传

5.1思想

前端表单->后端接收到文件本身->保存到服务器上->给数据库记录文件一些信息(如:文件路径)->库返回给nodejs相关信息->nodejs返回给前端

前端:

<form enctype="multipart/form-data" action="" method="post">
      <input type=file  name="fieldname"  />
</form>
5.2实现

multer->文件名会随机->fs模块改名->path系统模块解析磁盘路径

后端:multer 接受 form-data编码数据

multer中间件

multer 接受 form-data编码数据,所以,要求前端携带时注意一下,如:

5.3使用
//1 引入(在app.js里)
let multer  = require('multer');
//2 实例化  
let objMulter = multer({ dest: './upload' }); //dest: 指定 保存位置(存到服务器)
//安装中间件, 
app.use(objMulter.any());  //允许上传什么类型文件,any 代表任何类型  

中间件扩展了req请求体 req.files

app.post('/reg',(req,res)=>{
  req.files
})

​ fieldname: 表单name名
​ originalname: 上传的文件名(浏览器端选择的文件的名字)
​ encoding: 编码方式
​ mimetype: 文件类型
​ buffer: 文件本身
​ size:尺寸
​ destination: 上传后,文件保存的路径 (服务器端的路径)
​ filename: 上传后,保存后的文件名 不含后缀
​ path: 上传后,保存磁盘路径+保存后的文件名 不含后缀

前端使用form发送请求代码

  <form action="/upload" enctype="multipart/form-data" method="post" >
        <input type="text" name="username" >
        <input type="file" name="files" >
        <input type="submit" value="上传">
    </form>    

前端使用ajax发送请求:

<body>
    <form action="regSave" method="post" >
        用户名<input type="text" name="username" ><br/>
        头像:
        <img style="width:50px;height:50px" id="logoImg" />
        
            <input type="file" id="photoFile" style="display: none;" onchange="upload()">
        
        <a href="javascript:void(0)" onclick="uploadPhoto()">选择图片</a>
        
        <input name="logo" type="hidden" id="logoInput" >     <br/>   
        
        <input type="submit" value="注册" >
    </form>    
</body>
</html>
<script src="js/jquery-3.2.1.min.js"></script>
<script>
    function uploadPhoto() {
        $("#photoFile").click();//选择文件的按钮
    }
    //上传
   function upload(){
        if ($("#photoFile").val() == '') {
            return;
        }
        console.log($("#photoFile").val());
       
        var formData = new FormData();
       
        formData.append('photo', document.getElementById('photoFile').files[0]);
       
        $.ajax({
            url:"/upload",
            type:"post",
            data:formData,  
            contentType:false,
            processData:false,        
            success:function(str){
                console.log(str);//图片文件路径
                $("#logoImg").attr("src",str);
                $("#logoInput").val(str);
            }
        });
    };
</script>

六.BSR&&SSR&&SEO

6.1. BSR:客户端渲染(BSR:Browser Side Render)

客户端在操作DOM.

6.1.1渲染过程:

在服务端放了一个html 页面,客户端发起请求,服务端把页面发送过去,客户端从上到下依次解析,如果在解析的过程中,发现ajax请求,再次向服务器发送新的请求,客户端拿到ajax 响应的结果,渲染在页面上,这个过程中至少和服务端交互了两次

6.1.2缺点:

请求次数会增加,如果渲染逻辑复杂,数量大的话,尽量不要使用客户端渲染。

6.1.3优点:

网络上传输的数据量小,局部刷新

6.2.SSR:服务端渲染(SSR)
6.2.1渲染过程:

前端发送请求,服务器端从数据库中拿出数据,通过render()函数,把数据渲染在模板(ejs)里,产生了HTML代码,把渲染结果发给了前端,整个过程只有一次交互。

6.2.2优点:

提高渲染速度

6.2.3缺点:

网络上传输的数据量大了,页面全部刷新。

6.3. SSR与BSR的区别
  • 大多数网站里,既有服务端渲染又有客户端渲染 。
  • 服务端渲染(SSR)和客户端渲染(BSR)的区别
  • 客户端渲染不利于 SEO 搜索引擎优化,服务器端渲染有利于SEO搜索引擎优化
  • 服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的

例如:
京东网站:
1、商品列表就采用的是服务端渲染,目的了为了 SEO 搜索引擎优化
2、商品评论列表为了用户体验,而且也不需要 SEO 优化,所以采用是客户端渲染

6.4.SEO:搜索引擎优化(Search Engine Optimization
6.4.1作用:

提升网站关键词排名,提高访问量

6.4.2搜索引擎不友好的网站有哪些特征:

1、网页中大量采用图片或者Flash等富媒体(Rich Media)形式,没有可以检索的文本信息,而SEO最基本的就是文章SEO和图片SEO;
2、网页没有标题,或者标题中没有包含有效的关键词;
3、网页正文中有效关键词比较少(最好自然而重点分布,不需要特别的堆砌关键词);
4、网站导航系统让搜索引擎“看不懂”;
5、大量动态网页影响搜索引擎检索;
6、没有被其他已经被搜索引擎收录的网站提供的链接;
7、网站中充斥大量欺骗搜索引擎的垃圾信息,如“过渡页”、“桥页”、颜色与背景色相同的文字;
8、网站中缺少原创的内容,完全照搬硬抄别人的内容等。
9、网站地图,网站日记提取蜘蛛爬行轨迹。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值