因为最近工做须要又将node捡了起来。翻了下以前的笔记,想着把几篇比较详细的整理下分享出来。第一篇就来讲说常常会用到的cookie&session。node
众所周知http是一个无状态的协议,服务端没法跟踪客户端的状态。那么就会致使一个问题,如咱们以管理员身份登陆一个后台管理系统,登陆成功后跳转到管理页面,那在咱们进行操做时,服务器怎么知道咱们是否已经登陆过了呢?mysql
为了解决上面的问题,cookie诞生了。redis
cookie是http协议中的一部分,浏览器向服务器发请求,成功后服务器向浏览器返回一个cookie,那么之后浏览器向服务器发送的全部请求都会携带这个cookie。sql
首先安装express框架,固然你也可使用koa。这里演示代码都是express。
在express中cookie不是自带的,因此须要安装对应的中间件进行操做,koa中的cookie就是框架自带的就不须要另外安装。数据库
安装cookie-parser中间件express
npm i cookie-parser -D
npm
写cookie跨域
安装成功后,先引入cookie-parser。而后在任意路由中去尝试写一个cookie浏览器
const express = require('express'); const cookieParser = require('cookie-parser'); let server = express(); server.listen(8080); // 使用中间件 server.use(cookieParser()); server.get('/index',(req, res) => { // 使用了中间件后就能够访问req和res上的cookies对象 console.log(req.cookies); // 写cookie res.cookie('num', 10, { // domain: 'xxx.com', // path: '/', maxAge: 24 * 3600 * 1000 }) res.send('ok'); })
cookie的读取和设置都很简单,设置的时候有一些可选参数,安全
运行下代码,而后到浏览器中查看刚刚写入的cookie
打开浏览器F12,到Application中找到Cookies,就能够看到刚刚写入的cookie,名字和值以及有效期都是咱们设置的。再次刷新后咱们也能够在命令行中看到服务器打印的cookie。
简单的cookie读写就完成了。
安全隐患
这里咱们能够知道cookie是存在浏览器中的,而且请求服务器的时候会一并带过去。这样就必定会有安全隐患,咱们先把服务器写cookie的逻辑注释掉,从新运行服务器,而后尝试在浏览器中手动修改cookie。
这里咱们将值修改成10000。刷新页面后在命令行中能够看到服务器获取的值就是10000。
cookie就这样很容易的在浏览器中被咱们修改了。若是cookie存了一些比较重要的数据,后果会很是严重。
cookie签名
怎么样才能作到让服务器验证cookie准确性,让服务器发现cookie是否被人为修改。
就要用到cookie签名。修改下服务器代码。
// 密钥 server.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: ture maxAge: 24 * 3600 * 1000 }) res.send('ok'); })
这里我先现开启签名。而后运行代码
能够看到这回的cookie是一串乱码。将乱码复制出来是这样的。s%3A10.y4%2BaUbiQxjUS%2FvaGtU%2BaZnAZ9WxVHXy3O0zr%2BgoCdGk
%3A表明":",转换下获得以下:s:10.y4%2BaUbiQxjUS%2FvaGtU%2BaZnAZ9WxVHXy3O0zr%2BgoCdGk
经过以上得出签名后的cookie格式为:s:值.签名
这样若是咱们尝试修改其中的值,还会不会生效了呢?
将服务器设置cookie的代码注释掉,只打印cookie,而后在浏览器中修改cookie。
修改后的cookie由于没法经过服务器的签名验证,因此是没法获取的。这样就确保了cookie的安全性,虽然签名能够增长cookie的安全性,可是增大致积,因为cookie只有4k的存储空间,因此咱们只签名重要的信息。
cookie 虽然很方便,可是使用 cookie 有一个很大的弊端,就是存储在浏览器,虽然说能够对cookie进行签名,可是也不能保证cookie的绝对安全,而且将重要的信息存在客户端自己就是不安全的事情。同时cookie也受限于大小。为了解决这些问题session也诞生了。
session 中的数据是保留在服务器端的。session不会单独存储,会有标识,这个标识叫作session_id 或者 token。而且session是强制加密的。
一样咱们须要另外一个中间件操做session,cookie-sessionnpm i cookie-session -D
使用方式与cookie-parser相似,先引入cookie-session
const cookieSession = require('cookie-session');
而后进行循环密钥签名,密钥通常是经过程序生成的,可能几千几万条,这里方便演示,只写几条。
server.use(cookieSession({ keys: ['dasdas21fsdffedsfds4das21321', 'safdas454325235325trgtrthdfthd', '21ed2rf3245r23r2354r235235'], maxAge: 20 * 60 * 1000 // 有效期20分钟 }));
而后在接口中设置和获取session
server.get('index', (req, res) => { console.log(req.session); res.session['num'] = 10; res.send('ok'); });
运行代码,打开浏览器调试工具找到cookies,
cookie中有两个值,一个是session,一个是session.sig
将服务器中设置session的代码注释掉,再刷新页面,能够看到命令行中就打印了咱们设置的session值。
就算其余用户经过session劫持拿到了咱们的session值,可是每一个用户的session.sig签名是经过循环密钥生成的,数量庞大的循环密钥相同的概率很小。而且在浏览器手动修改session后,服务器也会感知到这个session和session.sig不是对应的。确保数据的安全性。同时也能够经过更换循环密钥和减小session有效期来提高安全性。
须要注意的是session是存在服务器的文件中。读写比较消耗性能。咱们能够将其保存在redis、内存、数据库中以优化性能。(如使用mysql-session)