CORS跨域
用node创建两个server
// server.js
const http = require('http');
const fs = require('fs');
http.createServer(function (request, response) {
console.log('request comes ', request.url);
const html = fs.readFileSync('test.html', 'utf8');
response.writeHead(200, {
'Content-Type': 'text/html'
});
response.end(html);
}).listen(8888);
// server2.js
const http = require('http');
http.createServer(function (request, response) {
console.log('request comes ', request.url);
response.writeHead(200, {
'Access-Control-Allow-Origin': '*'
});
response.end('123');
}).listen(8887);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8887/');
xhr.send();
</script>
</body>
</html>
请求已经发送,内容也返回了,只是浏览器在解析的时候发现没有设置
Access-Control-Allow-Origin
,就会自动拦截返回的内容
JSONP,即使server2.js不设置
Access-Control-Allow-Origin
也是可以成功的。利用了script,link,img等标签不受跨域限制的原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="http://127.0.0.1:8887/"></script>
</body>
</html>
允许的方法:GET,HEAD,POST
允许的Content-Type:text/plain,mutilpart/form-data,application/x-www-form-urlencoded
CORS限制
1、预请求,除了允许的几个不需要,其他都需要进行预请求
2、其他限制:
请求头限制,
XMLHTTPRequestUpload对象均没有注册任何事件监听器,
请求中没有使用ReadableStream对象
解决:可以设置允许的请求头
'Access-Control-Allow-Headers': 'X-Test-Cors'
同理:其他方法的限制也可以通过这种方式设置
'Access-Control-Max-Age': '1000'
这种方式告诉浏览器在1秒之内不再预请求可缓存性Cache-Control
属性值:
public:
客户端向服务器发送请求,经过的代理服务器等所有的都可以进行内容的缓存
private:
只有发起请求的客户端可以进行缓存
no-cache:
可以缓存,但每次请求都要发送到服务器端确认是否可以使用缓存
no-store:
不可以缓存,每次都要去服务器端拿新的内容过来使用到期
max-age = <seconds>:
缓存的过期时间 (浏览器端)
s-maxage = <seconds>:
主要是给代理服务器设置的
max-stale = <seconds>:
发起请求的一方带过去的,即使缓存过期了只要有这个属性设置的时间内,就还可以使用过期的缓存(浏览器中用不到)重新验证
must-revalidate:
如果设置了max-age并且缓存过期了,那么浏览器端就必须再次发起请求去服务器端获取数据,验证缓存的内容是否真的过期,不能直接使用过期的缓存
proxy-revalidate:
用于代理服务器
// 设置缓存
response.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=2000'
});
浏览器发送请求查看缓存的过程
Last-Modified:
上次修改时间
配合If-Modified-Since
或者If-Unmodified-Since
使用,一般都是前者
If-Modified-Since
可以在下次请求的时候带去服务器对比资源上次修改时间,如果相同说明资源没被修改过,服务器就告诉浏览器(返回304状态码)可以直接使用缓存,此时服务器不会再返回If-Modified-Since
值,因为没有变化。如果不一样Last-Modified
会被更新,下次再请求时浏览器带过来的If-Modified-Since
值就是这个Last-Modified
。
Etag:
签名,服务器生成的每个资源的唯一标识,只要有修改,该值就会有变化(典型案例就是对资源的URL进行一个hash的计算)
配合If-Match
或者If-None-Match
使用
过程同上,不一样的是,即使返回状态码304,也会再次生成一个新的Etag
返回给浏览器
对比
两者都是协商缓存,优先验证Etag
对于频繁修改的文件,前者只能检查到秒级
文件有时会定时重新生成相同内容,Last-Modified
不能很好辨别
Etag
每次服务端生成都需要进行读写操作,而Last-Modified
只需要读取操作,Etag
的消耗是更大的
Cookie
Cookie
是服务器端返回数据通过Set-Cookie
设置把一些内容保存到浏览器,不能跨域设置
浏览器下次请求的时候会自动带上,
键值对的形式
max-age
和expires
过期时间,同时存在的话以前者为准,两者区别在于前者是相对于客户端的时间,后者是相对于服务器的绝对时间,可能会出现稍微的偏差
Secure
只在HTTPS
的时候发送
HTTPOnly
设置之后表示无法通过document.cookie
修改存储的Cookie
多个Cookie
用数组表示
Session
最常用的方法是使用Cookie
保存Session
,不一样的是Session
是在服务器端,例如用户登录,每一个用户登录保存登录名密码在cookie
中之后会有一个唯一的id存放在服务器端,这个id
就是sessionId
,下次再登录的时候拿到登录用户的id
去跟sessionId
对比。
HTTP长连接
,也叫持久连接
HTTP请求的过程中要先建立一个TCP连接,在TCP连接的基础上进行HTTP的请求与接收等一系列交互,一次HTTP请求结束,如果立刻关闭TCP连接(短连接),就可以减少一直连接的消耗;但若是很快又会有请求,那么又需要进行三次握手的过程,就会有网络延迟的开销。如果一直开着(长连接),下次请求就可以直接在这个连接上请求发送。
一般情况下,网站的并发量都很大,如果每次都去重新创建TCP连接,开销可能远远超过一直开着连接的消耗,因次用长连接是一种比较好的解决方案,长连接可以设置timeout,在一定时间内没有请求发送就自动断开。
'connection': 'Keep-Alive'
因为对请求的处理都是串行的,要按照请求的先后顺序,因此一般网站都是先开6个HTTP请求,等到前六个加载完后面再等待
而在HTTP2.0里面实现了请求的并行处理,只需要开一个HTTP连接就可以实现并行
管线化
只有GET,HEAD可以,对POST有所限制,HTTP1.1支持,除此创建时不应启动,因为不确定对方是否支持管线化
不安全,如果一个管道中有10个连接,在发送出9个后,突然服务器告诉你,连接关闭了,此时客户端即使收到了前9个请求的答复,也会将这9个请求的内容清空,也就是说,白忙活了……此时,客户端的这9个请求需要重新发送。这对于幂等请求还好(比如get,多发送几次都没关系,每次都是相同的结果),如果是post这样的非幂等请求(比如支付的时候,多发送几次就惨了),肯定是行不通的。所以,post请求不能通过管道的方式进行通信!
数据协商
表示在请求头里设置的告诉服务器都需要什么数据,数据都是什么类型的,服务端根据这些信息返回相应的数据
在请求里面通过Accept
设置
Accept
:指定想获取的数据类型
Accept-Encoding
:数据的编码格式,服务端主要靠这个来决定使用哪种编码方式
Accept-Language
:返回的语言
User-Agent
:可以用来区分是PC端的页面还是移动端的页面
服务端返回设置Content
Content-Type
:对应Accept
,Accept
里面可以设置好几种不同的数据格式,服务端选择一种来返回,通过Content-Type
告知服务端
Content-Encoding
:编码方式
Content-Language
:语言
'X-Content-Type-Options': 'mosniff'
:有的请求没有表明请求的数据类型,服务器端就会预测这个类型,可能会造成安全隐患,这个设置可以防止预测
301/302
重定向
两个的区别是
301:
是永久重定向,第一次服务器设置完重定向页面之后会把这个路径保存在缓存里面,后面再次请求就不需要经过服务器继续设置了,基本上没有过期时间,尽可能长时间的缓存
302:
是临时重定向,每次访问的时候都需要服务器来指定跳转的页面
Content-Security-Policy(CSP)
内容安全策略
作用:
限制资源获取:
从哪里获取,请求发到哪个地方等都可以限制
限制方式:
default-src限制全局资源的请求范围,指定特定的资源类型
设置只能通过http/https的方式加载,不能直接在网页里面加载 ,外联的script是可以执行的。
还可以设置只能加载本域名下的脚本文件
'Content-Security-Policy': ' default-src \'self\' '
要用引号引起来
设置表单提交只能提交到本站有另外的方式
'Content-Security-Policy': ' default-src \'self\'; form-action \'self\' '
default-src
是限制所有类型,但各类型的限制可以如上图设置
还可以设置指定的网站
<div>
<div>this is content</div>
</div>
<script>
console.log('inline js');
</script>
<script src="/test.js"></script>
报告资源获取权:
向服务器报告一些没有预知到的情况以便做出一些调整
'Content-Security-Policy': ' default-src \'self\'; form-action \'self\'; report-uri /report '
report-uri /report
指定服务器的报告路径
'Content-Security-Policy-Report-Only': ' default-src 'self'; form-action 'self'; report-uri /report '
只报告但是不做限制
每一个限制的内容都会发一个report请求
除了在header中设置限制,还可以通过html页面中的meta标签设置,但是不能报告,报告只能在header里面设置
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; form-action 'self';">
网友评论