nodeJS入门(四)之身份验证

2023-11-14

一、bcrypt模块

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

1.1、简单介绍一下

bcrypt 算法相对来说是运算比较慢的算法,在密码学界有句常话:越慢的算法越安全。算法越慢,黑客破解成本越高。
通过salt 和 cost这两个值来减缓加密过程。bcrypt是单向的,而且经过salt 和 cost的处理,使其受rainbow攻击破解的概率大大降低,同时破解的难度也提升不少,相对于MD5等加密方式更加安全,而且使用也比较简单。
​ ​
bcrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。

其实,说这么多还是得学会怎么用!

1.2、安装

 npm  i  bcrypt --save

1.3、加密

我们使用bcrypt模块是为了给用户密码等隐秘信息加密,这样就能防止密码泄露等问题。

密码加密实例代码:

//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

这时,我们存入数据库的密码就变成加密过后的内容了,那在登录时怎么对比用户输入的密码是否正确呢?

接着往下看:

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

//格式:bcrypt.compareSync(用户登录时输入的密码,数据库中拿到的密码);
let isMatch = bcrypt.compareSync("123456","$2b$11$jMC6xi32MVFDApY.valjJ.f7W5gGXQoLj3VZlrPQ8Fik.pVQ/szTK");

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

这样就ok了!

二、身份验证

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

有问题肯定就有解决方案:(以下2种)

2.1、session(会话)

2.1.1、session实现身份验证的思路

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

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

2.1.2、session的业务流程

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

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

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

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

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

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

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

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

客户端携带 : cookie自动带

2.1.3、express-session

1、安装

npm i express-session -S

2、引入session模块:

var session = require('express-session');

3、创建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
	})
);

​ 4、保存变量:

req.session.变量名= 值;

​ 5、获取变量:

req.session.变量名

2.2、token

用的较多。

2.2.1、实现思路

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

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

2.2.2、实现步骤

  • jsonwebtoken的安装引入
npm i jsonwebtoken -S
let jwt = require('jsonwebtoken')
  • 生成签名(token)
let token = jwt.sign(payload, secretOrPrivateKey, [options, callback])
  • 校验token
jwt.verify(token, secretOrPublicKey, [options, callback])
token: 制作后的token
secretOrPublicKey] 解密规则,字符串,或者公钥
callback: 回调 err 错误信息 decode 成功后的信息
options] expiresIn 过期时间
  • token删除
    由客户端,负责删除,服务器端没有任何保存,

2.3、session vs token

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

解释一下多服务器粘性问题:

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

2.4、保存信息给浏览器(cookie)

  • 前端保存
cookie/localstorage
  • 后端操作cookie

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

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

格式:

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
   

 

2、删除cookie

res.clearCookie(name [, options]);

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] });

三、文件上传

3.1、基本思路

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

前端:

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

实现

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

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

3.2、multer中间件

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

<form enctype="multipart/form-data" />

使用

//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

4.1、BSR

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

客户端渲染:就是客户端在操作DOM.

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

  • 优缺点

缺点:请求次数会增加,如果渲染逻辑复杂,数量大的话,尽量不要使用客户端渲染。
优点:网络上传输的数据量小,局部刷新

4.2、SSR

服务端渲染(SSR)

渲染过程:前端发送请求,服务器端从数据库中拿出数据,通过render()函数,把数据渲染在模板(ejs)里,产生了HTML代码,把渲染结果发给了前端,整个过程只有一次交互。
优点:提高渲染速度
缺点:网络上传输的数据量大了,页面全部刷新。

4.3、SSR与BSR的区别

大多数网站里,既有服务端渲染又有客户端渲染 。

  • 服务端渲染(SSR)和客户端渲染(BSR)的区别

1)、客户端渲染不利于 SEO 搜索引擎优化,服务器端渲染有利于SEO搜索引擎优化
2)、服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的

4.4、SEO

SEO(Search Engine Optimization):搜索引擎优化

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nodeJS入门(四)之身份验证 的相关文章

随机推荐

  • 样本的均值和方差的无偏估计与测试阶段均值方差的关系

    什么是无偏估计 估计是用样本统计量 可以理解为随机抽样 来估计总体参数时的一种无偏推断 无偏估计的要求就是 估计出来的参数的数学期望等于被估计参数的真实值 所以呢 可以看出 估计值也是一个变量 因为是随机的嘛 真实值谁也不知道啊 因为你不可
  • 数据隐藏之Qt中d指针详解

    最近看到代码有用到了Qt中的Q D指针 就去学习了下 发现真的很好用 因此写一篇文章总结下 student h class CStudent public CStudent CStudent private string m name in
  • LeetCode 1. 两数之和

    题目链接 https leetcode cn problems two sum 思路如下 从前往后遍历 n u m s nums
  • 分销系统开发 分销商城开发 分销功能 Java开发"三级分销"业务功能

    众所周知 互联网时代 分享经济现在随处可见 各行各业都有各种分销系统 最为常见的就是三级分销 那么如何实现这个业务功能了 笔者通过本篇图文案例给大家分享一下实现过程 此处以二级分级分销实现为例 1 什么是二级分销 二级分销其实是一种让用户分
  • 【面试】赢时胜和花旗

    一 赢时胜 1 springmvc的底层 DispatcherServlet gt HandlerMaping gt Handler gt HandlerAda 2 spring注入的方式 spring循环依赖 注解是否解决了循环依赖 3
  • 从setContentView到onResume应用显示过程分析

    之前总体笼统地分析了Acitivity从启动到显示的过程 Activty启动到显示的过程 一 Activty启动到显示的过程 二 发现很多细节没有注意到 后续挑些过程中比较重要的部分重点分析 在上一篇文章分析了一个app从zygote到on
  • 惠普笔记本的Windows10和Ubuntu20.04双系统安装教程

    Windows10和Ubuntu20 04双系统安装教程 1 下载Ubuntu系统镜像到D盘 2 下载安装镜像工具到D盘 3 制作Ubuntu的系统安装盘 4 磁盘分区 5 GPT分区安装Ubuntu 6 结语 7 参考资料 惠普暗影精灵使
  • Python+selenium模块爬虫实战---拉勾网

    Python selenium模块爬虫实战 拉勾网 一 项目需求 二 selenium概述 三 爬虫思路 四 代码实现 五 完整代码 一 项目需求 项目需求 实现一个可以自动获取拉钩网 自定义搜索 的岗位招聘信息的爬虫程序 实现工具 Pyc
  • 【Unity InputSystem】基础教程(保姆级超详细超基础!!!)

    InputSystem基础教程 1 基础概念 1 1 前言 2 基础操作 2 1插件安装 2 2 如何创建InputActions 2 3 InputActions概念及结构关系 ActionMaps Actions ActionPrope
  • Disentangled Representation:IVIF

    DRF Disentangled Representation for Visible and Infrared Image Fusion DRF 可见光和红外图像融合的解纠缠表示 在本文中 我们通过将 解纠缠表示 应用于可见光和红外图像融
  • ssh登录一直提示修改密码解决

    用SSH登录就会出现用户登录失败 提示诸如 WARNING Your password has expired You must change your password now and login again 等等 在开发板手工修改 大致
  • java调用c++文件

    网上有很多例子 参照着执行有时候相对路径问题经常卡住了 实战了一把通过后 特重新整理一份 供小白参考 首先需要有一个含有native方法的java类 vi Users mac work git javademo src main java
  • 一点整理

    1 美国在2010年以后开始流行数字化转型的 在2010年以前 2006年社交网络FB YOU 在2004 2006 Web2 0热之前 企业是无法直接触达到每个消费者的 2006年Amazon电子商务 这个是我瞎凑的 但因为是在线交易所以
  • 入门Python必备100道练习题

    给大家整理了这份今天给大家分享100道Python练习题 在此之前 先给大家推荐一个工具 是一个对 Python 运行原理进行可视化分析的工具 Python Tutor 点击 Next 按钮就会根据执行步骤显示原理 对新手理解代码运行原理有
  • C++day01

    一 C 简介 本贾尼 斯特劳斯特卢普 于1979年4月在贝尔实验室负责分析UNIX系统的内核的流量情况 希望有一款更加模块化的工具 于1979年10月开始着手开发一种新的编程语言 在C语言的基础上增加了面向对象机制 这就是C 的来历 在19
  • 从量子物理到AI医疗,这位清华博士后想用十年弥补病理医生的"百年缺口"

    大数据文摘出品 作者 易琬玉 根据WHO下属 国际癌症研究机构 公布的最新全球癌症数据报告 2018年全球新增癌症诊断病例约1910万 死亡病例约960万 约1 5男性和1 6女性在一生中会罹患癌症 1 8男性和1 11女性因癌症而死亡 对
  • 安全应急响应案例

    1 产生背景 1988年11月发生的莫里斯蠕虫病毒事件 Morris Worm Incident 致使当时的互联网络超过10 的系统不能工作 该案件轰动了全世界 并且在计算机科学界引起了强烈的反响 为此 1989年 美国国防部高级研究计划署
  • linux系统ipcclean命令,Linux学习笔记29——IPC状态命令

    一 IPC IPC是进程间通讯 在前面 我们相继学习了进程间通讯机制有信号量 内存共享 消息队列 状态命令 ipcs 和删除命令 ipcrm 提供了一种检查和清理IPC机制的方法 二 状态命令 1 显示信号量状态用ipcs s 2 显示共享
  • 华为OD机试真题- 狼羊过河【2023Q2】【JAVA、Python、C++】

    题目描述 一农夫带着m只羊 n只狼过河 农夫有一条可载x只狼 羊的船 农夫在时或者羊的数量大于狼时 狼不会攻击羊 农夫在不损失羊的情况下 运输几次可以完成运输 返程不计入次数 输入描述 输入参数为 m n x m 为羊的数量 n为狼的数量
  • nodeJS入门(四)之身份验证

    身份验证 一 bcrypt模块 1 1 简单介绍一下 1 2 安装 1 3 加密 二 身份验证 2 1 session 会话 2 1 1 session实现身份验证的思路 2 1 2 session的业务流程 2 1 3 express s