第一:CSRF攻击
假设我们不使用跨域就会有这样的情况发生,如果有个心怀鬼胎的人,想知道你的隐私,他先搞了一个网站,让你去登录,并且你毫无意识的情况去点击了,这样你的隐私就泄露了,而且可以利用这个便利,查看你的个人隐私资料,并且代替你去做一些比较危险的事情,然而你毫不知情,这样多可怕,感觉被人肉了。太可怕了,所以,赶紧想到一个办法,就是希望找个东西,可以作为防火墙一样的东西,把这些人或者事物,抵挡住外面。只有相同的东西可以访问,这样就出现了跨域资源共享(CORS)。
举例说一下:
有一个小小的东西叫cookie大家应该知道,一般用来处理登录等场景,目的是让服务端知道谁发出的这次请求。如果你请求了接口进行登录,服务端验证通过后会在响应头加入Set-Cookie字段,然后下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中,服务端就能知道这个用户已经登录过了。知道这个之后,我们来看场景:
1.你准备去清空你的购物车,于是打开了买买买网站www.maimaimai.com,然后登录成功,一看,购物车东西这么少,不行,还得买多点。
2.你在看有什么东西买的过程中,你的好基友发给你一个链接www.nidongde.com,一脸yin笑地跟你说:“你懂的”,你毫不犹豫打开了。
3.你饶有兴致地浏览着www.nidongde.com,谁知这个网站暗地里做了些不可描述的事情!由于没有同源策略的限制,它向www.maimaimai.com发起了请求!聪明的你一定想到上面的话“服务端验证通过后会在响应头加入Set-Cookie字段,然后下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中”,这样一来,这个不法网站就相当于登录了你的账号,可以为所欲为了!如果这不是一个买买买账号,而是你的银行账号,那……
这就是传说中的CSRF攻击浅谈CSRF攻击方式。
看了这波CSRF攻击我在想,即使有了同源策略限制,但cookie是明文的,还不是一样能拿下来。于是我看了一些cookie相关的文章聊一聊 cookie、Cookie/Session的机制与安全,知道了服务端可以设置httpOnly,使得前端无法操作cookie,如果没有这样的设置,像XSS攻击就可以去获取到cookieWeb安全测试之XSS;设置secure,则保证在https的加密通信中传输以防截获。
下面这个可以详细的解释跨域和为啥跨域
https://www.zhihu.com/question/26379635
第二: 什么是同源策略?
同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略限制以下几种行为:
Cookie、LocalStorage 和 IndexDB 无法读取
DOM和JS对象无法获得
AJAX 请求不能发送
第三: 跨域资源共享(CORS)
简单来说同源指的是"协议+域名+端口"三者相同,同源策略实际上是浏览器限制一个域名与另外一个域名的资源的交互的规则。


跨域就是一个域名请求另外一个域名的资源,例如www.a.com网站请求www.b.com/b.js javascript文件,这就是跨域。
而在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。
第五:9种跨域解决方案
第六:重点讲cors跨域
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
浏览器将CORS跨域请求分为简单请求和非简单请求。
首先先介绍简单请求,
什么是简单请求:
动词为get/post/head,没有自定义请求头,Content-Type是application/x-www-form-urlencoded,multipart/form-data或text/plain之一,通过添加以下响应头解决:
简单请求就是请求方式是get,post,head 而headers头部不写,
Content-Type: 只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
这样后台返回的值是这样的







什么是非简单请求?
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
(通过个人测试。如果请求是post,headers,却填写,依旧需要预检)
可以通过添加自定义的x-token请求头使请求变为preflight请求


预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。请求头信息里面,关键字段是Origin,表示请求来自哪个源。除了Origin字段,"预检"请求的头信息包括两个特殊字段。

代码:
app.js

proxy.js

server.js

index.html

对于代码的解说:
首先第一步:
假设如果 4000端口 开启,并且调用接口/api/user, 是正常访问的,
如果使用 3000端口,去访问 4000端口,就出现跨域,
为了解决跨域,现在index.html中定义基本访问端口
axios.defaults.baseURL = 'http://localhost:4000'
第二步:利用axios请求/api/users
const res = await axios.post('/api/users')
第三步:判断 method === 'GET' || method === 'POST' && url === '/api/users' 添加 请求头
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
res.setHeader('Content-Type', 'application/json');
第四步:这是localhost:3000 去访问localhost:4000 通过了,跨域成功
第五步:在headers中添加x-token,并使用post提交数据,而在后台使用options进行预检
const res = await axios.post('/api/users',{foo:'bar'},{
headers:{'X-Token','yunzhu'}
})
if (method === 'OPTIONS' && url === '/api/users') {
res.writeHead(200, {
'Access-Control-Allow-Credentials': 'true',
"Access-Control-Allow-Origin": "http://localhost:3000",
"Access-Control-Allow-Headers": "X-Token,Content-Type",
"Access-Control-Allow-Methods": "PUT"
})
res.end();
}
第六步:如果要携带cookie信息,则请求变为credential请求:
index.html
axios.defaults.withCredentials = true {开启cookie}
app.js
if (method === 'GET' || method === 'POST' && url === '/api/users') {
res.setHeader('Set-Cookie', 'cookie1=va222;') {新增cookie}
res.setHeader('Access-Control-Allow-Credentials', 'true'); {允许客户端携带验证信息}
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify([{ name: "tom", age: 20 }]))
}
参考文献
https://github.com/amandakelake/blog/issues/62