再次拿起node。翻了翻之前的笔记,想着整理几篇比较详细的文章分享一下。第一篇会讲到经常用到的cookies&session。众所周知http是无状态协议,服务端无法追踪客户端的状态。那么就会导致问题。比如我们以管理员身份登录后台管理系统,登录成功后跳转到管理页面,那么服务器在操作的时候怎么知道我们是否已经登录了呢?为了解决以上问题,cookie诞生了。Cookie是http协议的一部分。浏览器向服务器发送请求。成功后,服务器返回一个cookie给浏览器。那么浏览器向服务器发送的所有请求都会携带这个cookie。先安装express框架,当然你也可以用koa。这里的演示代码很明确。express中并没有内置cookie,需要安装相应的中间件来操作。koa中的cookie是自带的框架,不需要单独安装。安装cookie-parser中间件npmicookie-parser-DWritecookie安装成功后,首先引入cookie-parser。然后尝试在任意路由中写入cookieconstexpress=require('express');constcookieParser=require('cookie-parser');letserver=express();server.listen(8080);//使用中间件server.use(cookieParser());server.get('/index',(req,res)=>{//使用中间件后,可以访问req和res上的cookies对象console.log(req.cookies);//写入cookieres.cookie('num',10,{//domain:'xxx.com',//path:'/',maxAge:24*3600*1000})res.send('ok');})cookies的读取和设置非常简单。设置的时候有一些可选参数,domain:存储的域名,cookie是不跨域的,子域名可以存储在主域名中可以访问,但是如果存在于子域名中,则主域无法访问名称。所以这里一般会有一个主域名,防止子域名访问cookies。path:存储路径,类似于domain,所以一般指定根路径。maxAge:validityperiod(milliseconds)运行代码,然后去浏览器查看刚才写入的cookie,打开浏览器F12,在Application中找到Cookies,可以看到刚才写入的cookie,名称和值以及有效期是我们的设置。再次刷新后,我们在命令行也可以看到服务端打印的cookie。简单的cookie读写就完成了。安全隐患在这里我们可以知道cookie是存在于浏览器中的,在请求服务器的时候会带上。这样一来,必然存在安全隐患。我们先把服务端写入cookies的逻辑注释掉,重新运行服务端,然后尝试在浏览器中手动修改cookies。这里我们将值修改为10000,刷新页面后,在命令行中可以看到服务器获取到的值为10000。cookies很容易在浏览器中被我们修改。如果cookie中存储了一些重要数据,后果将非常严重。cookie签名如何才能让服务器验证cookie的准确性,让服务器发现cookie是否被人为修改过。有必要使用cookie签名。修改服务器代码。//keyserver.use(cookieParser('dasdasdasdasfewg315nkl23k1ml41m24kl1nm5kol312n5kl32n5oj3n4oi1jm4o1k2m4'));使用cookieParser中间件时添加一个签名密钥,通常是随机生成的字符串,然后在设置cookie时添加几个参数。server.get('/index',(req,res)=>{//签名cookie需要通过signedCookies访问console.log(req.signedCookies);res.cookie('num',10,{//httpOnly:true,//secure:true,signed:turemaxAge:24*3600*1000})res.send('ok');})httpOnly:设置cookie只能由服务端操作,前台看不到secure:Cookiesinged只能在https的情况下使用:设置cookie是否签名这里我先启用签名。然后运行代码可以看到这次的cookie是一串乱码。乱码就是这样复制出来的。s%3A10.y4%2BaUbiQxjUS%2FvaGtU%2BaZnAZ9WxVHXy3O0zr%2BgoCdGk%3A表示“:”,转换如下:s:10.y4%2BaUbiQxjUS%2FvaGtU%2BaZnAZ9WxVHXy3O0zr%2BgoCdGk通过上述得到的签名cookie的格式是:s:值。Signatureso如果我们尝试修改这个值,它还会生效吗?把服务器设置cookie的代码注释掉,只打印cookie,然后在浏览器修改cookie。修改后的cookie无法通过服务器的签名验证,无法获取。这确保了cookie的安全性。虽然签名可以增加cookie的安全性,但它增加了大小。由于cookie只有4k的存储空间,所以我们只对重要信息进行签名。虽然会话cookie非常方便,但是使用存储在浏览器中的cookie有一个很大的缺点。虽然可以对cookies进行签名,但是不能保证cookies的绝对安全,将重要信息存放在客户端本身是不安全的。事情。同时,cookies也有大小限制。为了解决这些问题,session也诞生了。会话中的数据保存在服务器端。session不会单独存储,而是会有一个标识符,称为session_id或token。并且会话是强制加密的。同样的,我们还需要另外一个中间件来操作session,cookie-sessionnpmicookie-session-D的使用方式和cookie-parser类似,首先引入cookie-sessionconstcookieSession=require('cookie-session');然后进行循环密钥签名,密钥一般由程序生成,可能有几万个密钥。这里为了演示方便,只写了几个。server.use(cookieSession({keys:['dasdas21fsdffedsfds4das21321','safdas454325235325trgtrthdfthd','21ed2rf3245r23r2354r235235'],maxAge:20*60*1000minutes'setinserver(getstheindexininterface20periodandinterface2}',(req,res)=>{console.log(req.session);res.session['num']=10;res.send('ok');});运行代码,打开浏览器调试工具找到cookie,cookie里面有两个值,一个是session,一个是session。即使其他用户通过session劫持获得了我们的session值,每个用户的session.sig签名也是通过循环密钥生成的,大量循环密钥相同的概率很小。并且浏览器手动修改session后,服务端也会感知到session与session.sig不对应。确保数据安全。同时,还可以通过更换循环密钥和缩短会话有效期来提高安全性。需要注意的是,session是保存在服务器的文件中的。读写比较消耗性能。我们可以将其保存在redis、内存、数据库中以优化性能。(比如使用mysql-session)
