Cookie 存在的问题
用户可以随意篡改 Cookie
Session 与 Cookie 的关系
一般来说,Session 基于 Cookie 来实现。
Cookie
- 服务器通过 Set-Cookie 头给客户端一串字符串
- 客户端每次访问相同域名的网页时,必须带上这段字符串
- 客户端要在一段时间内保存这个Cookie
- Cookie 默认在用户关闭页面后就失效,后台代码可以任意设置 Cookie 的过期时间
- 大小大概在 4kb 以内
Session(不翻译)
- 将 SessionID(随机数)通过 Cookie 发给客户端
- 客户端访问服务器时,服务器读取 SessionID
- 服务器有一块内存(哈希表)保存了所有 session
- 通过 SessionID 我们可以得到对应用户的隐私信息,如 id、email
- 这块内存(哈希表)就是服务器上的所有 session
LocalStorage
- LocalStorage 跟 HTTP 无关
- HTTP 不会带上 LocalStorage 的值
- 只有相同域名的页面才能互相读取 LocalStorage(没有同源那么严格)
- 每个域名 localStorage 最大存储量为 5Mb 左右(每个浏览器不一样)
- 常用场景:记录有没有提示过用户(没有用的信息,不能记录密码)
- LocalStorage 永久有效,除非用户清理缓存
SessionStorage(会话存储)
1、2、3、4 同上
5.SessionStorage 在用户关闭页面(会话结束)后就失效。
缓存与 304 的区别
- 缓存没有请求。
- 304 有请求,有响应,但是响应没有第四部分。
使用Sesssion保存信息
- 我们先复习一下Cookie的内容
- 服务器先通过Set-Cookie给响应添加一串字符串,内容我们可以不管
- 每次请求相同页面的时候,带上这个Cookie,谁发过来的,谁会查看这个Cookie
- Cookie用法:
- 用户登录成功就会得到一个Cookie
- 用户访问首页的时候,请求就会加上这个字符串,如果登录成功,将渲染相关信息到页面中
- 服务器会读取这个Cookie,看到是哪个用户登录,可以将返回登录成功信息,如果Cookie是空的,就返回页面到注册页面
- Cookie容易被用户篡改,该怎么办?
-
Session可以解决这个问题,就是让用户无法进行更改
-
如果我们还有一个账户信息,那么我们直接更改Cookie,刷新页面就可以拿到密码信息了
-
我们只需要让用户猜不到就可以了。我们之前在SetCookie的时候,直接将账号信息放到里面去了,
- 我们可以创建一个哈希叫session,每次都将登录信息放入这个session里面,但是返回的cookie是一个随机数ID。
- 我们可以通过这个随机数ID找对应的用户信息,
- 但是不能根据id来找用户信息,因为id是随机的,我们并不知道什么样的随机数ID是有效的
-
这样,我们返回的cookie就是一个随机数,这样用户就无法随意篡改了
-
怎么利用这个sessionId呢?我们需要将每次登录的session记录到文件里面或者其他方式保存下来,我们在访问首页的时候,去读取一下这个sessionId在session里面对应的值。这个session一定要记录下来,否则无法读取。
-
我们可以根据这个随机ID找到email,然后根据email找到密码,但是其他账户的密码不容易被发现,因为即便这个cookie被更改,也不会出现响应。
- 总结一下:什么是session?
- 服务器通过cookie给浏览器一个sessionId
- sessionId对应服务器里面的一小块内存
- 每次用户访问服务器的时候,服务器就通过sessionID读取对应的session拿到用户的隐私信息
- 随机数就是用来防止伪造的,这样就相对安全
localStorage简介
- localStorage是HTML5提供的一个API
- 里面有getItem和setItem,以及clear函数
-
localStorage的实质是一个哈希,session是服务器上面的哈希表,localStorage是浏览器上面的哈希表
-
在没有使用之前,localStorage里面的哈希表是没有数值的,我们可以设置哈希值,使用localStorage.setItem('a', '1')设置哈希
- 存储的东西可以是函数形式的string,会自动转换成string,setItem(键, 值)
-
当我们使用这个API存储对象的时候,会变成[object Object],因为对象转成字符串就会变成这样
-
我们为了解决上面这种BUG,可以使用JSON形式的字符串,或者直接使用JSON.stringfy(对象)
-
localStorage取值的时候,使用getItem就好了,使用localStorage.clear()就是清空
localStorage用法
- JS变量:在刷新页面的时候,会回归原始值。关闭页面的时候,就完全消失
- 有没有什么办法,可以让变量值在第一个页面的时候存在,第二个页面也存在,并且是不断变化的?
-
localStorage是存在C盘的一个文件里面的,所以不管页面刷新还是更换,都会在那个文件中
- 每次刷新,就会发现其实a在加1
-
所有的页面都用这个文件,这叫持久化存储,一些文件可以保存到本地的localStorage文件,用于以后使用
-
一个典型应用场景实例:比如当网页改版的时候,我们需要提醒我们拥有这些新功能,但是当我们每次刷新的时候就都需要提示,这个很是麻烦,我么可不可以记录下我们已经知道了呢,不用更新
-
存入的字符如果过大是无法存入的
-
sessionStorage会自动清理,当页面刷新或者关闭,即并非永久存储,用法跟localStorage一样
- 面试题1:cookie和session的关系
- 一般来说,Session是基于Cookie实现的,Cookie是Session的基石
- 面试题2:cookie和localStorage的区别
- Cookie会被浏览器带到服务器上面去,但是localStorage不会
- sessionStorage和localStorage的区别,
- SessionStorage在用户关闭会话(网页)的时候就会结束
不基于Cookie的Session
-
中间不用session,我们可以不写cookie,可以直接将sessionId返回给前端
-
前端拿到这个就存到localStorage里面去
-
点击提交的时候,就可以发送请求,这个id保存在session网页网址中,并可以返回密码
- Cookie是可以跨页面的,之前没有LocasStorage的时候,是使用Cookie进行跨页面数据存储操作的,写到cookie中的数据一定会带到服务器,会影响请求时间
- 前端一定不要读/写Cookie,
缓存控制的Cache-Control
- HTTP缓存
-
我们添加js和css路径,并让两者的文件很大,我们发现我们每次请求的时候都会要比较长的时间去请求
- 如何让我们的CSS和JS请求速度加快呢?
- 可以搜索cache control mdn查询相关语法。
-
添加这样一句话,response.setHeader('Cache-Control', 'max-age=30')
-
我们再次请求的时候,发现这个js文件的响应里面出现Cache-Control。此时还是会有响应时间的
- 当我们再次请求的时候,发现这个JS文件的请求时间就会很短, 这个Cache-Control: max-age=30的意思就是30s内再次请求就是最新的,无需更新,即30s内无需请求这个文件
response.setHeader('Cache-Control', 'max-age=30')
-
第一次请求需要很多时间,Server会将文件返回,当我们使用max-age = 30的时候,当30s内再次请求,server不会发出响应,而是直接从Chrome的内存中直接返回上一次的请求;过了30s就可以再次请求
如何更新缓存-Cache-Control
- 首页一般不允许设置缓存,因为如果连首页都缓存,用户就拿不到刷新,无法获取最新版本,刷新和网页回车是不一样的
- 首页一般不使用缓存,但是JS和CSS一般设置的时间是10年,也就是3000000000多秒
-
只有相同的URL才会使用缓存,如果URL稍微变化了,就会发送请求,重新刷新。比如更改一下请求CSS的url,CSS就会刷新,重新请求
- 所以升级的时候,我们只需要稍微变动一下URL,就可以促使用户进行更新
- 通常的做法是,设置很长的缓存时间,如果升级就更改一下url,让其进行更新
-
有的那些后面会加随机数,随机数变化就会更新
- Cache可以让浏览器在一段时间内不访问浏览器,直接用本地的硬盘或者内存作为响应,这样就省略了请求速度回非常快,当需要更新的时候,只需要在入口处将url变一下就好了,当这个url跟以前使用的url不一样,就会发送请求进行更新
控制缓存-Expires
-
Cache-Control是比较新的
- Expires设置的是缓存具体失效的时间,时间格式是格林威治时间,并且这个时间是本地时间,容易错乱
- response.setHeader('Expires', 'Thu, 19 Mar 2020 13:20:30 GMT')
ETag
- md5是一个摘要算法
-
应用场景:用于计算是否是同一个文件,不一样一定不是同一个文件内容
- md5可以将微小的差异放大
- 这个跟HTTP有什么关系呢?这就涉及ETag,ETag可以给一个资源一个内容
-
我们可以使用nidejs算md5的,它有专门的md5的库
-
在server里面拿到文件的md5,然后放在response里面
-
再一次刷新就会将上一次的md5放入这次的请求头的if-none-match里面,如果没有变化就不会更新
- 使用Cache-Control是直接不请求,使用ETag是请求但是如果没变化就不下载
- 还有一种是last-modified