前端天罗地网
网络
TCP
三次握手(创建连接)
客户端向服务端发起连接请求,一个带有SYN(sychronize)标志与连接序列号x的数据包
服务端收到连接请求,回复ACK确认号x+1确认收到,并携带SYN表示同意连接请求,y作为连接序列号
客户端收到SYN+ACK+y数据包,再回复ACK确认号y+1,连接建立
四次挥手(关闭连接)
客户端向服务端发起关闭信号FIN(finish),即不再发送请求但可以接收请求
服务端收到关闭请求,回复确认号ACK,此时还可继续发送请求
服务端不再需要发送请求后,发送关闭信号FIN
客户端收到服务端关闭信号,回复ACK确认号,关闭连接
HTTP
Header
Content-type
前端对发起的请求所携带的请求体的格式声明,告知后端如何处理接收到的数据:
application/json
json格式application/x-www-form-urlencoded
常用于简单文本表单提交,以url编码(序列化)的格式放在post请求的请求体中,并不是get请求那般拼接url
multipart/form-data
;boundary=----随机字符串
常用于复杂的携带文件的表单提交,表单数据以boundary分隔符隔开,boundary由请求库自动生成也可以自定义
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
----WebKitFormBoundary7MA4YWxkTrZu0gW // 必须以--开头
Content-Disposition: form-data; name="username"
John
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain
(文件内容)
----WebKitFormBoundary7MA4YWxkTrZu0gW-- // 结尾加--表示表单的末尾
text/plain
纯文本text/html
html文档
Data-type
前端在请求库中设置(例如ajax的dataType属性),告知后端,前端希望收到什么类型的响应数据
json
: 期望服务器返回JSON格式的数据。xml
: 期望服务器返回XML格式的数据。text
: 期望服务器返回纯文本数据。html
: 期望服务器返回HTML文档。
状态码
Https
Http2.0
SSL
网页
解析流程
SEO
安全
XSS(Cross-Site Scripting)
CSRF(Cross-Site Request Forgery)
缓存
Cookie
为解决Http不带有状态的问题,服务器在客户端保留的少量状态数据,一般不超过4KB。
Cookie包含cookie名,值,到期时间Expire或 Max-Age ,所属域名 Domain ,生效路径Path
服务端
通过响应请求设置Set-Cookie字段配置cookie,一个Set-Cookie只能设置一个cookie键值对,可以使用多个Set-Cookie设置多个cookie。
客户端
通过document.cookie设置Cookie的内容,发送请求时添加请求头Cookie字段发送cookie。
设置 window.navigator.**cookieEnable **为false则禁用了cookie的读取和写入,可以让请求不接收也不发送cookie。
属性
Expire :绝对时间,过期时间点。
Max-Age :相对时间,多长时间后过期。
Domain :默认cookie只在当前域和子域名有效,domain前端 只能设为自身或上级域名 ,其中上级域名也不能是公共域名(github.io)或顶级域名(.top/.com),设置之后在自身与子域名间生效。
Path :cookie在 当前路径及子路径范围内生效 ,只有路径匹配时才发送携带Cookie的请求到服务器
HttpOnly :只有发起HTTP请求可以带cookie,无法通过JS访问document.cookie,防止XSS(Cross-Site Scripting)攻击。 只有后端可设置 ,前端如果设置HttpOnly则不能通过js访问cookie,这与该配置悖论。
Secure :只有发起https请求才能携带cookie,页面可以为http。如果前端设置该字段需页面也为HTTPS才可设置。
SameSite :限制跨站http请求中cookie的发送,防止CSRF(Cross-Site Request Forgery)攻击:
strict
完全禁止跨站cookie;
Lax
允许部分跨站请求,如子域名共享,如导航跳转url的GET请求(location.href、a标签),<form method='GET'>
等;(Chrome、FireFox默认值)
None
完全允许跨站请求携带cookie(必须Secure,所以也限制了前端页面必须HTTPS)。
document.cookie
document.cookie可以获取当前网站所有的cookie,但设置cookie只能和服务端一样,一次设置一个
document.cookie = 'test1=hello';
document.cookie = 'test2=world';
document.cookie // test1=hello;test2=world
cookie设置完便不可读取属性,只能通过设置过期时间来删除cookie
// 删除fontSize属性
document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';
答疑
为什么有domain还需要sameSite?
domain与path只限制了cookie作用域,无法限制跨站请求,即跨站网站虽无法获取cookie,但跨站的link/script/img标签,xhr,表单请求等,仍可携带cookie,这是浏览器兼容的遗留问题,所以这就需要sameSite来保证安全了。
cookie能不能跨域?
cookie访问权限
总结:配置可支持同站跨域;无法通过配置实现跨站,需借助其他方式。
- 同站跨域:配置实现
- window.navigator.cookieEnable = true(默认);
- domain="父级域名",子域名间可以共享;
- path="/",或其他路径,总之保证包含你想共享cookie的子路径;
- 跨站:借助其他方式实现
- window.navigator.cookieEnable = true(默认);
- 通过postmessage发送document.cookie,或其他跨域请求的方案
请求携带cookie
总结:同站跨域默认支持部分;配置支持跨站。
- 同站跨域(子域名之间)
- 同站跨域的cookie访问权限
- sameSite配置:
- sameSite="Lax"(默认),支持导航跳转url请求和Form Get表单提交,不需要CORS配置;
- sameSite="None",同时Secure=true,支持所有请求,后端必须配置CORS;
- 请求库配置withCredentials = true 允许请求携带cookie
- 跨站
- window.navigator.cookieEnable = true(默认);
- sameSite="None",同时Secure=true;
- 请求库配置withCredentials = true
- 配置CORS(
Access-Control-Allow-Origin
和Access-Control-Allow-Credentials
);
强缓存
浏览器直接从本地缓存中读取资源,不发送请求到服务器。
Cache-Control
max-age=<seconds>
: 缓存最大有效时间(秒)。no-cache
: 协商缓存 ,向服务器验证缓存是否过期,如果服务返回304 Not Modified,前端则使用缓存。no-store
: 不缓存任何内容。public
: 允许所有用户缓存资源,即共享缓存,可以被浏览器、CDN、代理服务器缓存。private
: 仅允许单个用户缓存资源,即只能被浏览器缓存。immutable
:表示资源永远不会变,无需验证直接使用缓存。
Expires
指定资源的过期时间(HTTP/1.0 的字段,逐渐被 Cache-Control
取代)。
Cache-Control: max-age=3600, public
Expires: Wed, 01 Jan 2025 00:00:00 GMT
html文件上如果通过meta标签配置了缓存策略则会优先以html文件的配置为准
<meta http-equiv="Cache-Control">
协商缓存
浏览器向服务器发送请求,验证本地缓存是否仍然有效。
Last-Modified
和 If-Modified-Since
- 资源最后的修改时间(
Last-Modified
),由服务器返回。 - 浏览器下次请求时带上
If-Modified-Since
,服务器据此判断资源是否更新。
ETag
和 If-None-Match
:
- 服务器返回资源的唯一标识(
ETag
)。 - 浏览器下次请求时带上
If-None-Match
,服务器根据标识判断资源是否更新。
Last-Modified: Wed, 01 Jan 2020 00:00:00 GMT
ETag: "abc123"
Session
Token JWT
请求
同源策略
如果非同源,共有三种行为受到限制。
(1) 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB。
(2) 无法接触非同源网页的 DOM。
(3) 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)。
跨域方案
CORS
CORS 是一个 W3C 标准,全称是“跨源资源共享”(Cross-origin resource sharing),或者通俗地称为“跨域资源共享”。它允许浏览器跨源发出 XMLHttpRequest
请求,克服了 AJAX 只能同源使用的限制。
简单请求
简单请求的判定
(1)请求方法是以下三种方法之一。
- HEAD
- GET
- POST
(2)HTTP 的头信息不超出以下几种字段。
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
简单请求的流程
简单请求直接发起CORS请求,请求头自动增加Origin字段。
如果Origin不在服务器跨域许可范围,则返回正常的HTTP回应,浏览器发现没有Access-Control-Allow-Origin则会抛出错误,此时状态码可能仍然是200。
正确的Origin则会得到服务器新增的三个header:
(1) Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时 Origin
字段的值,要么是一个 *
。
(2) Access-Control-Allow-Credentials
是否允许发送 Cookie,默认Cookie 不包括在 CORS 请求之中。同时也需要配置 xhr.withCredentials=true ,且Access-Control-Allow-Origin不能是*,因为cookie必须是同源的
(3) Access-Control-Expose-Headers
CORS 请求时,XMLHttpRequest
对象的 getResponseHeader()
方法只能拿到6个服务器返回的基本字段:Cache-Control
、Content-Language
、Content-Type
、Expires
、Last-Modified
、Pragma
。如果想拿到其他字段,就必须在 Access-Control-Expose-Headers
里面指定 Access-Control-Expose-Headers:字段名
非简单请求
JSONP
原理源码
利用 <script>
标签不受同源策略限制的特点,通过动态创建script标签,将GET请求当作脚本src发起,并让其携带回调函数,服务器把数据拼接到回调函数里返回,例如 foo(123)
,浏览器会当作script标签返回的脚本,进行代码解析后并执行
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
Script[crossOrigin]
Script标签的crossOrigin属性具有以下的值:
anonymous
:进行跨源请求,但不发送用户凭据(如 Cookie、HTTP 认证信息等)。use-credentials
:进行跨源请求,并发送用户凭据。
虽然Script标签不受同源限制,但也有一些功能限制,例如无法拿到加载错误信息,不能对DOM进行操作,此时crossOrigin字段可以解决这些问题:
- 错误处理:设置
crossOrigin
属性可以让浏览器提供更详细和准确的跨域脚本加载错误信息,有助于开发人员进行调试和错误排查。 - 资源共享和缓存:通过正确设置
crossOrigin
,可以更好地利用浏览器的缓存机制。当多个页面使用相同的跨域脚本且设置相同时,浏览器可以更有效地缓存和复用这些资源。 - 凭证传递:如果需要在跨域请求中传递用户凭证(如 Cookie、HTTP 认证信息等),就需要通过设置
crossOrigin="use-credentials"
来明确告知浏览器。 - 符合 CORS 规范:遵循跨源资源共享(CORS)的规范和最佳实践,确保跨域请求的安全性和可预测性。
WebSocket
WebSocket 协议不受同源策略的限制,可以实现跨域的双向通信