一、cookie

上一个文章介绍了实用node写了一个服务,以及调用api去操作数据库的一个前后端分离的demo,这次重点记录一下前后端登陆操作的一个部分。登陆认证是一个项目中比较重要的部分,接下来我将使用cookie的模式来实现登陆认证!

cookie的组成

cookie是浏览器中特有的一个概念,它就像浏览器的专属卡包,管理着各个网站的身份信息。

每个cookie就相当于是属于某个网站的一个卡片,它记录了下面的信息:

  • key:键,比如「身份编号」

  • value:值,比如张博的身份编号「14563D1550F2F76D69ECBF4DD54ABC95」,这有点像卡片的条形码,当然,它可以是任何信息

  • domain:域,表达这个cookie是属于哪个网站的,比如123.com,表示这个cookie是属于123.com这个网站的

  • path:路径,表达这个cookie是属于该网站的哪个基路径的,就好比是同一家公司不同部门会颁发不同的出入证。比如/news,表示这个cookie属于/news这个路径的。(后续详细解释)

  • secure:是否使用安全传输

  • expire:过期时间,表示该cookie在什么时候过期

当浏览器向服务器发送一个请求的时候,它会瞄一眼自己的卡包,看看哪些卡片适合附带捎给服务器

如果一个cookie同时满足以下条件,则这个cookie会被附带到请求中

  • cookie没有过期

  • cookie中的域和这次请求的域是匹配的

  • 比如cookie中的域是123.com,则可以匹配的请求域是123.com、www.123.com、234.123.com等等

  • 比如cookie中的域是www.123.com,则只能匹配www.123.com这样的请求域

  • cookie是不在乎端口的,只要域匹配即可

  • cookie中的path和这次请求的path是匹配的

  • 比如cookie中的path是/news,则可以匹配的请求路径可以是/news、/news/detail、/news/a/b/c等等,但不能匹配/blogs

  • 如果cookie的path是/,可以想象,能够匹配所有的路径

  • 验证cookie的安全传输

  • 如果cookie的secure属性是true,则请求协议必须是https,否则不会发送该cookie

  • 如果cookie的secure属性是false,则请求协议可以是http,也可以是https

如果一个cookie满足了上述的所有条件,则浏览器会把它自动加入到这次请求中

具体加入的方式是,浏览器会将符合条件的cookie,自动放置到请求头中。

如果把它用于登录场景,就是如下的流程:

登录请求

  1. 浏览器发送请求到服务器,附带账号密码

  1. 服务器验证账号密码是否正确,如果不正确,响应错误,如果正确,在响应头中设置cookie,附带登录认证信息(至于登录认证信息是设么样的,如何设计,要考虑哪些问题,就是另一个话题了,可以百度 jwt)

  1. 客户端收到cookie,浏览器自动记录下来

后续请求

  1. 浏览器发送请求到服务器,希望添加一个管理员,并将cookie自动附带到请求中

  1. 服务器先获取cookie,验证cookie中的信息是否正确,如果不正确,不予以操作,如果正确,完成正常的业务流程

二、处理登陆APi接口

接下来就是处理登陆这个api接口:

const express = require("express")
const router = express.Router()
const user = require("../../serveAPI/userService")
const {asyncHandler} = require("../getResult")
const cryptor = require("../../util/crypt")router.post("/login",asyncHandler(async (req,res,next) =>{const result = await user.login(req.body.loginId,req.body.loginPwd)if (result) {//如果result存在则登录成功//设置cookie//给浏览器用cookie//cookie-parse给了一个默认加密,其中有默认密钥可以设置const value = result.idcryptor.encrypt(value)res.cookie("token",result.id,{path:"/",domain:"localhost",maxAge:3600*24*10000,// signed:true,})//给其他应用 如手机端res.header("authorization",value)}return result;}
))

当我们调用这个接口之后,就会从数据库中访问这个用户(根据用户名和密码),这个密码时使用md5进行加密,然后解密的:

当返回这个结果的时候,我们就使用cooke方法进行给res请求结果中设置cookies,将token设为用户的id,剩下的domain,还有path,maxAge都可以视情况而定,但是这里的id就可以在浏览器端使用document.cookie获取到,然后提取出来id,我们在服务端,也可以设置让js不能获取cookie,防止跨站脚本攻击,但是还是不安全,因为这个数据是明文的,可以在浏览器中的cookie中看到数据,而cookie-parse里面提供一个自动加密的属性,就是signed为true,就会给这个cookie里的token值自动加密,之后取到也可以自动解密,但是有个很严重的问题,这里cookie是浏览器特有的一个属性,在其他端虽然可以使用但是没有像浏览器这样专门设置这个cookie模块,来处理请求,所以我们在这个请求头中,留一手,给请求头中再设置一个authorization的值为用户id,这样不管是pad端,手机端都可以处理这个请求内容,所以当设置这个authorization这个键之后,cookie-parse只能去处理这个cookie中的token而不能处理authorization,所以加密这个事情还得我们来做,这里使用node里面提供的这个crypto模块,来进行加密:


const secret = Buffer.from("mm7h3ck87ugk9l4a");
const crypto = require("crypto");
const iv = Buffer.from("jxkvxz97409u3m8c");//加密一个字符串
exports.encrypt = function (str) {const cry = crypto.createCipheriv("aes-128-cbc", secret, iv);let result = cry.update(str, "utf-8", "hex");result += cry.final("hex");return result;
};//解密一个字符串
exports.decrypt = function (str) {const decry = crypto.createDecipheriv("aes-128-cbc", secret, iv);let result = decry.update(str, "hex", "utf-8");result += decry.final("utf-8");return result;
};

上面是一个js文件导出两个函数,一个用于加密,一个用语解密;

使用对称加密算法:aes算法 128位密钥(16个字节的字符串),其中mm7h3ck87ugk9l4a是用随机数转字符串拼接获取Math.random(),toString(36).slice(-8)+Math.random(),toString(36).slice(-8)

Buffer是node里面的一个类,JS里的String对象,存储的是字符串,而且是Unicode编码的。

我们使用node内置库crypto,crypto.getCiphers()可以看到crypto所有的加密函数,而我们使用第一个aes-128-cbc,接下来是准备一个iv,随机向量 ,一般来说密钥固定,向量是不固定的,这里我为了简便实用固定的。而这个密钥是存储在服务端的,所以很难进行解密,这样就会让数据有安全保障。第一层保障是这个密钥,如果这个密钥泄漏,下一个保障就是iv向量,这里写的固定的,当然也可以写那种不固定的,使用到js中的闭包;

module.exports = function(){//准备一个ivconst iv = Buffer.from(Math.random(),toString(36).slice(-8)+Math.random(),toString(36).slice(-8));return {encrypt(str){const cry = crypto.createCipheriv("aes-128-cbc", secret, iv);let result = cry.update(str, "utf-8", "hex");result += cry.final("hex");return result;},decrypt(str){const decry = crypto.createDecipheriv("aes-128-cbc", secret, iv);let result = decry.update(str, "hex", "utf-8");result += decry.final("utf-8");return result;},}
}

这里我们直接导出一个函数,这个函数执行后就会给予一个对象,对象有两个方法,第一个是加密,第二个是解密,而这两个函数都使用到函数里定义的变量iv,当我们调用一次这个函数,就会生成一个iv,所以这个iv是不固定的,也是无法获取的,这样就完善了token加密的一个步骤,让数据更加的安全!

三、使用中间件获取cookie

我们使用cookie-parser插件写入中间件,之后再每一次的请求中都会在req对象中注入cookies属性,用于获取传递过来的cookie,也会在res对象中注入获取cookie的方法,所以操作起来就更加方便。

我们引入自己写的cookieMiddleware中间件

/*** 用于解析token*/
const { getErr } = require("./getResult");
const cryptor = require("../util/crypt")// 用于解析token
module.exports = (req, res, next) => {let token = req.cookies.token;// 获取cokkie
// let token = req.signedCookies.token;if(!token){//其他的端获取tokentoken = req.headers.authorization}if(!token){handleNonToken(req,res,next)return;}const userId = cryptor.decrypt(token)console.log(userId,"认证通过啦~~~");next()
};//处理没有认证的情况
function handleNonToken(req, res, next) {res.status(403).send(getErr("不好意思,您没有token令牌无法登陆哦~", 403));
}

以上可以看出,当我们调用接口的时候,就会进行token认证,首先从req中获取cookie如果没有的话,就会在authorization中获取,如果都没有那么就报错,如果有一个有,就进行解密,然后执行下一个中间件,至此,使用cookie方式登陆的模式完成!

前端登陆之cookie篇相关推荐

  1. Web前端数据存储—cookie机制(设置,获取,删除cookie)

    今天看到cookie机制就来记录一下,我们前端一般存储cookie都是在登录的时候进行的,两种,选一个就行(其实都一样,只不过一个明细化了). 我们先了解一下 cookie: HTTPCookie,通 ...

  2. 前端修改服务器cookie,前端中怎样设置cookie

    这次给大家带来前端中怎样设置cookie,前端中设置cookie的注意事项有哪些,下面就是实战案例,一起来看一下. cookie是什么:是一种用来在客户端硬盘上存储信息的手段. 为什么用?:可以用来存 ...

  3. 好程序员web前端分享HTML基础篇

    好程序员web前端分享HTML基础篇,最近遇到很多新手,都会问,如果要学web前端开发,需要学什么?难不难学啊?多久能入门之类的问题?那么今天好程序员就先来给大家分享一下web前端学习路线:HTML基 ...

  4. php curl获取登陆cookie,PHP curl 模拟登陆 获取cookie

    PHP curl 模拟登陆 获取cookie求助 菜鸟学习使用PHP curl模拟登陆,等陆weiphon论坛时用以下代码成功,登陆www.xiaomi.com就死活成功不了,求助啊.窃以为是cook ...

  5. web前端细解cookie那些事

    web前端细解cookie那些事,在互联网时代,IT行业飞速发展,带动了web前端开发行业的兴趣.由于行业新兴起时间不久,专业人才缺乏,薪资待遇较高,已成为众多IT学子选择就业的首选,今天就为分享一些 ...

  6. html5 判断分享,好程序员HTML5大前端分享之函数篇

    好程序员HTML5大前端分享之函数篇,将代码编写在函数中,就可以避免在非必要情况下调用该代码,也就是说我们可以让一段代码在特定情况下再去执行. function 关键字:该关键字表示要声明一个函数. ...

  7. 前端flv.js设置缓冲时间和大小_好程序员web前端细解cookie那些事

    好程序员web前端细解cookie那些事,在互联网时代,IT行业飞速发展,带动了web前端开发行业的兴趣.由于行业新兴起时间不久,专业人才缺乏,薪资待遇较高,已成为众多IT学子选择就业的首选,今天就为 ...

  8. WEB前端优化之内容篇

    WEB前端优化之内容篇 Web前端优化过程中难免对相关的前台内容进行重新安排.其中主要的一些点如下: 1尽量减少 HTTP 请求 (Make Fewer HTTP Requests) 作为第一条,可能 ...

  9. Qt 之 模仿 QQ登陆界面——功能篇(一)

    一.简述 今天是2017年第一篇技术文章,12月末事情太多,一直没来得及更新博客.今天继 Qt 之 模仿 QQ登陆界面--样式篇 这一篇 来简单地看一下对登录界面做的一些功能,主要是登录用户下拉列表和 ...

最新文章

  1. Bmu计算机,高性能定点DSP位处理单元BMU的 - 处理器/DSP - 电子发烧友网
  2. Oracle BIEE (Business Intelligence) 11g 11.1.1.6.0 学习(2)RPD资料档案库创建
  3. 怎样下载C/C++的免费、开源且跨平台IDE——Code::Blocks
  4. 物联网避坑 3 大指南!
  5. B端表格设计实战指南
  6. 给xen虚拟机添加硬盘分区格式化
  7. 企业家“大战”初代网红:李彦宏、董明珠、罗永浩同时直播,谁更秀?
  8. 设计模式(一)---单一职责原则
  9. 【Shell】数值比较参数
  10. spring学习--AOP五个通知
  11. date命令 简单使用
  12. spring mybatis 项目源码
  13. 上热搜!武大学生用Python敲出樱花开放 | 附源码
  14. FileReader 对象实现图片预览
  15. java格式化xml字符串_XML串的格式化输出
  16. 不用跑项目,组件效果所见即所得,绝了~
  17. xposed检测方法
  18. android旋转的列表,Android利用layer-list实现ProgressBar顺时针及逆时针旋转
  19. Java自学教程!docker运行镜像无反应
  20. 测试公开课资料系列02--Postman之chai.js断言应用

热门文章

  1. 【Linux】虚拟地址空间 --- 虚拟地址、空间布局、内存描述符、写时拷贝、页表…
  2. maven complie报错汇总
  3. MYSQL 基础篇(补)
  4. 【数据结构与算法】之深入解析“扫雷游戏”的求解思路与算法示例
  5. 告赢了!程序员拒绝春节带电脑回家工作被开除,判决获赔19.4万!
  6. php 游戏开发swoole,《基于 Swoole 的对战游戏实践》开课啦
  7. CleanCode-函数
  8. 天琴协议_天琴座:新秀背后
  9. Cent OS 使用nohup 启动 Springboot避坑
  10. 计算机和运筹学就业方向,运筹学与控制论专业就业方向