目录

前端通信(渲染、http、缓存、异步、跨域)

HTTP与HTTPS,HTTP版本、状态码

请求头,响应头

区别小结:均用于 鉴权

cookie、session

cookie、token

session、token

LocalStorage、SessionStorage、Cookie

缓存

强制缓存:Cache-Control:max-age(HTTP1.1)>Expires(1.0)

js、css、img等静态资源、第三方库公共资源设置强缓存

协商缓存

If-Modified-Since/Last-Modified

If-None-Match/ETag:内容变动太快,时间没变

服务器生成的资源标识符(哈希值/实体标签)

html 资源设置协商缓存

存储:js/图片(内存,刷新),css(硬盘,渲染)

本地存储

Cookie:存储键值对

引入:http无状态

分类

会话性cookie(Session Cookie)(默认):客户端内存

持久性Cookie(Persistent Cookie):客户端硬盘中(txt )

属性

必选:Name,Value

作用域

Domain:域名或 ip(作用域,无法跨域,与端口无关),默认是当前域名

一级域名和二级域名之间是允许共享使用的

Path(默认 '/',即全路径):指定 cookie 在哪个路由下生效

安全性

HttpOnly(默认不设置):为 true 时,只有 http 能读取, js不能读,防止恶意脚本通过Cookie 攻击

但能通过 Application 中手动修改 cookie,所以还是没办法防止 XSS 攻击

Secure(默认false):为true表示只有 https 的请求可以携带,true防止中间人攻击

SameSite(默认不设置):限制第三方 URL 是否可以携带 cookie(Chrome51 新增,chrome80+ 强制)(即跨域时 是否携带cookie,防止CSRF工具)

Strict:仅允许发送同站点请求的 cookie

Lax(默认):在顶级导航和POST请求中发送Cookie,但在跨站点的GET请求中不会发送

None:任意发送 cookie,但需要同时设置 Secure,即必须采用 https

内存优化

Max-Age(保留时长(秒数))>Expires(时间戳,客户端时间)

Priority(默认不设置):优先级

Chrome :Low/Medium/High,当 cookie 数量超出时,低的会优先被清除

开发中模拟不同权限的用户

手动:开发者模式Application

浏览器扩展小程序:一键获取/设置多个

JS:document.cookie

设置:

 public /index.html /script 

删除:expires=new Date(0)

HttpOnly为 true 时,只有 http 能读取, js不能读取,防止XSS

跨域请求

服务端设置cookie:SameSite=None(任意发送cookie)Secure=true(https)

响应头Access-Control-Allow-Credentials=true(允许发送Credentials)

请求头withCredentials=true(会发送Credentials)

WebStorage:本地存储键值对,不参与服务器的通信

window.addEventListener('storage'

在标签页/窗口触发,当前页面刷新不触发

localStorage:string存储形式

存储对象:JSON.prase/stringify

应用:来存储有关标签页的信息,恢复会话

sessionStorage

IndexDB(运行在浏览器的非关系型数据库)

实现授权的方式:cookie、session、token、OAuth

认证(Authentication):验证用户

授权(Authorization):授权第三方应用

凭证(Credentials):标记访问者身份

Token(令牌)

Acesss Token:访问资源接口(API)时所需要的资源凭证

token 的身份验证流程 ​编辑​Refresh Token:刷新 access token 的 token

刷新

硬性刷新:忽略缓存,重新请求

正常加载:缓存


前端通信(渲染、http、缓存、异步、跨域)

HTTP与HTTPS,HTTP版本、状态码

请求头,响应头

区别小结:均用于 鉴权

cookie是容器,装session信息(value)、 session id /token(key)

  • session 可以存放在服务器(以 session id 为钥匙获取信息),也可以存放在浏览器

  • token/session/session id 界限模糊(一般新技术使用 token,传统技术使用 session id)

session id 一般存在 cookie 里,自动带上

token 一般主动放在请求中,例如设置请求头的 Authorization 为 bearer:<access_token>

cookie:保存用户的会话信息和状态

Session :记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息

Token令牌:访问资源接口(API)时所需的资源凭证,使服务端无状态化,不会存储会话信息

cookie、session

cookiesession
关系记录http请求的状态首次会话创建session Cookie
存储地
客户端内存(会话)/硬盘(持久)
服务端,session cookie 客户端内存
大小一般单个cookie 保存的数据大小不超过 4kb无限制
数量单个域名最多保存 30 个 cookie(浏览器不同有差异)无限制
value的存储格式字符串对象

cookie、token

tokencookie
跨域

token 完全由应用管理,因此可以避开同源策略

服务器端生成管理,默认不能跨域

不同端口上可以共享相同的 Cookie

跨域请求默认不会携带 Cookie,以保护用户信息

CORS(跨源资源共享):通过设置 HTTP 头部,允许不同源之间的请求。

在 CORS 请求中:允许携带 Cookie

设置 withCredentials 为 true

在服务器端设置 Access-Control-Allow-Credentials 为 true

session、token

sessiontoken
存储地服务端,session cookie 客户端内存localstorage/cookie
安全

身份认证 Token 比 Session 好,因为每一个请求都有签名、避免CSRF攻击(跨站请求伪造)

移动端

不能共享给其它网站或者第三方 App

允许第三方调用 API 接口/共享用户数据

兼容性问题

  • 不是所有的移动浏览器都完全支持Cookie,尤其是一些老旧的或定制化的浏览器。
  • 在原生移动应用中,Cookie的处理需要额外的编程工作,因为原生平台(如iOS和Android)通常不会像Web浏览器那样自动处理Cookie
  • session 需要基于 cookie 实现,所以移动端常用的是 token

LocalStorage、SessionStorage、Cookie

同源=协议,域名,端口号一致;

同源看作一台电脑,不同盘的资源看成不同路径和参数啥的。最开始的路径就是指某台电脑的某个路径的文件

特性LocalStorageSessionStorageCookie
数据范围同源域名同源 + 路径 + 标签页【同路径】可通过 Domain【域名】/Path【路径】 灵活配置
持久性持久,手动/代码清除标签页关闭即清除可设置过期时间 (Expires/Max-Age)
跟随请求(自动在 HTTP 头中发送)
可访问性仅客户端 JavaScript仅客户端 JavaScript客户端和服务器均可访问

缓存

强制缓存:Cache-Control:max-age(HTTP1.1)>Expires(1.0

Expires:Mon, 29 Jun 2020 11:10:23 GMT

「服务器的时间和浏览器的时间可能并不一致」,所以HTTP1.1提出新的字段代替它。

常见的 Cache-Control 指令值及其含义:

  1. public: 表示响应可以被任何缓存(包括客户端和代理服务器)存储。

  2. private: 表示响应只能被客户端缓存,不应该被代理服务器缓存。

  3. no-cache: 要求缓存服务器在返回响应前验证其有效性,即使缓存有有效的副本也会发送请求到原始服务器进行验证。

  4. no-store: 指示请求和响应都不应该被缓存,所有内容都必须从服务器重新获取。

  5. max-age=<seconds>: 指定响应可以被缓存的最长时间,单位为秒。

js、css、img等静态资源、第三方库公共资源设置强缓存

​状态码为灰色的请求则代表使用了强制缓存,请求对应的Size值则代表该缓存存放的位置,分别为from memory cache 和 from disk cache。

  • 浏览器读取缓存的顺序为memory –> disk。
  • 访问URL–> 200 –> 关闭标签页 –> 重新打开URL–> 200(from disk cache) –> 刷新 –> 200(from memory cache)

协商缓存

If-Modified-Since/Last-Modified

如果将资源的最后修改日期Last-Modified<=If-Modified-Since,会 304(Not Modified)

If-None-Match/ETag:内容变动太快,时间没变

服务器生成的资源标识符(哈希值/实体标签)

使用了该头部,即为条件请求,若请求标识符==资源的当前标识符,则304

If-None-Match: "d41d8cd98f00b204e9800998ecf8427e"

条件请求是指客户端在发起请求时附带一些条件,以便服务器根据这些条件来决定是否返回实际的响应内容。

可以理解为代码中的if,输入确定,但输出根据实际情况而不同

html 资源设置协商缓存

存储:js/图片(内存,刷新),css(硬盘,渲染)

本地存储

Cookie:存储键值对

引入:http无状态

分类

会话性cookie(Session Cookie)(默认):客户端内存

因为存储在内存,所以刷新不会改变(保持连接但重新请求),但重新打开浏览器会改变id

Max-Age:失效时间(单位秒)

负数,该 cookie 为临时 cookie关闭浏览器即失效,

如果为 0,表示删除该 cookie 。默认为 -1

从低到高排序

在客户端和服务器之间传递会话标识(Session ID

Session Cookie 的 value 是与用户会话相关的唯一标识符,通常称为 Session ID

隐私浏览模式中用户关闭  整个 浏览器时失效

否则,会话恢复上次打开的标签页,导致浏览器保留会话信息,包括Session Cookie

迫使服务器为 session 设置了一个失效时间,

当距离客户端上一次使用 session 的时间超过这个失效时间时,

服务器就认为客户端已经停止了活动,才会把 session 删除以节省存储空间​​​​​​

持久性Cookie(Persistent Cookie):客户端硬盘中(txt )

直至生存期到或用户直接在网页中单击“注销”等按钮结束会话时才会失效

  1. 记住登录状态: 当用户选择 "记住我" 或类似选项时,网站可以使用持久性 Cookie 在用户下一次访问时自动登录,而不需要重新输入用户名和密码。

  2. 个性化设置: 网站可以使用持久性 Cookie 存储用户的偏好和个性化设置,例如语言选择、主题选项、字体大小等,以便在用户下一次访问时保持一致的用户体验。

  3. 跟踪用户行为: 持久性 Cookie 可以用于跟踪用户在网站上的行为,例如记录用户的浏览历史、购物车内容或其他与用户个性化体验相关的信息。

  4. 广告定向: 在在线广告领域,持久性 Cookie 可以用于跟踪用户的兴趣和行为,从而提供更有针对性的广告体验。

  5. 统计分析: 网站可以使用持久性 Cookie 收集匿名的统计数据,用于分析用户行为、改进网站性能和提升用户体验。

用户硬盘

属性

必选:Name,Value

 cookie 都是依靠 set-cookie 头设置,且不允许 JavaScript 设置。 <cookie-name>=<cookie-value> 键值对

Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly

Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure

// Multiple attributes are also possible, for example:
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
作用域

图片

Domain:域名或 ip(作用域,无法跨域,与端口无关),默认当前域名
一级域名和二级域名之间是允许共享使用的

如果设成 .example.com,那么子域名 a.example.com 和 b.example.com 都可以使用.example.com 的 cookie;反之不可以。

Path(默认 '/',即全路径):指定 cookie 在哪个路由下生效
安全性
HttpOnly(默认不设置):为 true 时,只有 http 能读取, js不能读,防止恶意脚本通过Cookie 攻击
但能通过 Application 中手动修改 cookie,所以还是没办法防止 XSS 攻击

Secure(默认false):为true表示只有 https 的请求可以携带,true防止中间人攻击
SameSite(默认不设置):限制第三方 URL 是否可以携带 cookie(Chrome51 新增,chrome80+ 强制)(即跨域时 是否携带cookie,防止CSRF工具)

一个站点可以包含多个网页,例如个人博客

Strict:仅允许发送同站点请求的 cookie
Lax(默认):在顶级导航和POST请求中发送Cookie,但在跨站点的GET请求中不会发送

"顶级导航" 指的是从一个站点的一个URL跳转到另一个站点的URL,通常是通过点击链接输入网址来实现的。

None:任意发送 cookie,但需要同时设置 Secure,即必须采用 https
内存优化
Max-Age(保留时长(秒数))>Expires(时间戳,客户端时间
Priority(默认不设置):优先级
Chrome :Low/Medium/High,当 cookie 数量超出时,低的会优先被清除

开发

模拟不同权限的用户

手动:开发者模式Application

“跨站 Cookie ,https才能读取,携带(HttpOnly:true,Secure:true)
本地测试走 HTTPS,避免调试两行泪。”

浏览器扩展小程序:一键获取/设置多个

获取项目网页中的cookies,然后在本地的项目网页中设置

JS:document.cookie

document.cookie=‘username=JohnDoe; sessionID=abc123; theme=dark’

设置:
 public /index.html /script 
<script>document.cookie = "sso_ticket=ST-xx-cn"</script>

读取

function getCookie(name: any) {
    // 获取指定名称的 cookie 值
    var start = document.cookie.indexOf(name + '=');
    // 查找 cookie 字符串中是否存在指定名称的 cookie
    if (start != -1) {
        // 如果找到了,查找 cookie 的结束位置
        var end = document.cookie.indexOf(';', start);
        // 查找分号(;)作为 cookie 的结束标志。如果没有找到分号,表示 cookie 是最后一个
        if (end == -1) {
            // 如果没有分号,表示这是 cookie 字符串的末尾
            end = document.cookie.length;
        }
        // 解码 URL编码的字符(例如 %20 被解码为空格)
        return decodeURI(document.cookie.substring(start + name.length + 1, end));
    } else {
        // 如果没有找到指定名称的 cookie,返回空字符串
        return '';
    }
}
删除:expires=new Date(0)

new Date(0) :970年1月1日UTC时间,0代表的是 Unix 时间戳的起始时间

document.cookie = ‘cookieName=; expires=${new Date(0)}; path=/;’;

基本刷新只是从本地硬盘中重新拿取数据到浏览器

HttpOnly为 true 时,只有 http 能读取, js不能读取,防止XSS

服务端设置,如Node.js/Express

const express = require('express');
const app = express();

app.get('/set-cookie', (req, res) => {
    res.cookie('sessionID', 'abc123', { httpOnly: true, maxAge: 3600000 }); // 设置 HttpOnly 属性
    res.send('HttpOnly cookie has been set');
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});
cookie方法类

如果是敏感信息(如 Token),应建议后端在设置 Cookie 时加上 HttpOnly(JS 无法读取)和 SameSite=Lax

export class CookieHelper {
    /**
     * 设置 Cookie
     * @param name 键名
     * @param value 值
     * @param days 过期时间(天),不传则为会话级 Cookie
     * @param path 路径,默认为根路径 '/'
     */
    static setCookie(name: string, value: string, days?: number, path: string = '/') {
        let expires = '';
        if (days) {
            const date = new Date();
            // 转化为毫秒处理,更精确
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = `; expires=${date.toUTCString()}`;
        }
        //encodeURIComponent 比 encodeURI 更彻底地转义特殊字符(如 ?, =, & 等),确保 Cookie 格式不被破坏。
        document.cookie = `${name}=${encodeURIComponent(value)}${expires}; path=${path}`;
    }

    /**
     * 获取 Cookie
     */
    static getCookie(name: string): string {
        const reg = new RegExp(`(^| )${name}=([^;]*)(;|$)`);
        const arr = document.cookie.match(reg);
        return arr ? decodeURIComponent(arr[2]) : '';
    }

    /**
     * 删除 Cookie
     * 删除时必须指定相同的 path 才能成功
     */
    static removeCookie(name: string, path: string = '/') {
        // 直接将过期时间设置为过去,无需先获取值
        this.setCookie(name, '', -1, path);
    }
}

跨域请求

服务端设置cookie:SameSite=None(任意发送cookie)Secure=true(https)
响应头Access-Control-Allow-Credentials=true(允许发送Credentials)
请求头withCredentials=true(会发送Credentials)

WebStorage:本地存储键值对不参与服务器的通信

window.addEventListener('storage'

在标签页/窗口触发,当前页面刷新不触发
// 监听 localStorage 数据变化的 storage 事件
window.addEventListener('storage', (event) => {
  console.log('storageArea',event.storageArea);//localStorage 或 sessionStorage
  console.log('Key:', event.key);
  console.log('Old value:', event.oldValue);
  console.log('New value:', event.newValue);
  console.log('URL:', event.url);
});

localStorage:string存储形式

存储对象:JSON.prase/stringify
JSON.parse(localStorage.getItem('curMsg'));
localStorage.setItem('curMsg',JSON.stringify({
            taskId: this.data.taskId,
            resultText: this.currentMd,
        }))
应用:来存储有关标签页的信息,恢复会话
localStorage.setItem('uname','zwq')
localStorage.getItem('uname')
localStorage.key(0)
localStorage.removeItem('uname')
localStorage.clear()
开发
export class LocalStorageHelper {
    /**
     * 存储数据
     * @param key 键名
     * @param value 支持字符串、对象、数组等任意可序列化类型
     */
    static setItem(key: string, value: any): void {
        try {
            // 自动将对象转换为 JSON 字符串
            const serializedValue = typeof value === 'string' ? value : JSON.stringify(value);
            localStorage.setItem(key, serializedValue);
        } catch (error) {
            // 处理空间溢出(QuotaExceededError)或序列化失败
            console.error('LocalStorage setItem error:', error);
        }
    }

    /**
     * 获取数据
     * @param key 键名
     * @returns 自动解析后的数据或原始字符串
     */
    static getItem<T = any>(key: string): T | null {
        const value = localStorage.getItem(key);
        if (!value) return null;

        try {
            // 尝试解析 JSON,如果报错则说明是原始字符串
            return JSON.parse(value) as T;
        } catch {
            return value as unknown as T;
        }
    }

    /**
     * 删除指定数据
     */
    static removeItem(key: string): void {
        localStorage.removeItem(key);
    }

    /**
     * 清空当前域名下所有 LocalStorage
     */
    static clear(): void {
        localStorage.clear();
    }
}

sessionStorage

将上述 localStorage 替换为 sessionStorage

  • 最大的坑:在同一个浏览器里打开两个窗口(标签页)访问同一个网址,它们的 sessionStorage互不相通的。这让它很难处理“多开页面”时的状态同步。

刷新 vs. 新开

  • 刷新页面:数据会保留(这是它唯一的优点)。

  • 新开标签页/窗口:即使网址一模一样,它也会给你一个全新的、空的 sessionStorage

移动端 H5 的不稳定性

在某些移动端浏览器(尤其是 iOS 的部分 WebView)中,当用户从 App 切换到后台,或者因为内存不足导致页面被系统卸载时,sessionStorage 有时会提前失效,导致用户填了一半的表单数据直接消失。


什么时候用它比较好?

虽然它有局限性,但在以下特定场景下它是“神药”:

  1. 敏感数据的临时存储:比如你从列表页点进详情页,需要临时存一下当前的滚动位置或搜索过滤条件。

  2. 防止表单重复提交:可以用它存一个 isSubmitting 状态。

IndexDB运行在浏览器的非关系型数据库)

IndexedDB: 一些浏览器可能使用 IndexedDB,这是一种更强大的客户端存储解决方案,用于存储更大的结构化数据。

实现授权的方式:cookie、session、token、OAuth

OAuth(Open Authorization)授权框架

认证(Authentication):验证用户

互联网中的认证:

  • 用户名密码登录
  • 手机号接收验证码

授权(Authorization):授权第三方应用

针对第三方应用,用户授予第三方应用访问该用户某些资源的权限

  • 你在安装手机应用的时候,APP 会询问是否允许授予权限(访问相册、地理位置等权限)
  • 你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息)

凭证(Credentials):标记访问者身份

实现认证和授权的前提是需要一种媒介(证书) 来标记访问者的身份

当用户登录成功后,服务器会给该用户使用的浏览器颁发一个令牌(token),这个令牌用来表明你的身份,每次浏览器发送请求时会带上这个令牌

Token(令牌)

Acesss Token:访问资源接口(API)时所需要的资源凭证

简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)

用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库

特点:

  • 服务端无状态化(不用存放 token )、可扩展性好
  • 支持移动端设备
  • token 完全由应用管理,所以它可以避开同源策略 

token 的身份验证流程 ​Refresh Token:刷新 access token 的 token

如果没有 refresh token,也可以刷新 access token,但每次刷新都要用户输入登录用户名与密码,会很麻烦。

有了 refresh token,可以减少这个麻烦,客户端直接用 refresh token 去更新 access token,无需用户进行额外的操作。

  • Access Token 的有效期比较短,当 Acesss Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Token,如果 Refresh Token 也失效了,用户就只能重新登录了。
  • Refresh Token 过期时间是存储在服务器的数据库中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。

刷新

硬性刷新:忽略缓存,重新请求

com/ctrl+R

正常加载:缓存

com/ctr+Shift+R

更多推荐