CORS跨域限制以及预请求验证

CORS 的使用

创建两个服务器,进入对应目录,命令行 node server.js,node server2.js,启动服务器。

server.js 会读取 test.html,在8888端口显示,test.html发送跨域请求8887服务器,server2.js通过设置'Access-Control-Allow-Origin': 'http://127.0.0.1:8888'允许跨域。

浏览器认为localhost和127.0.0.1不同,所以本地用127.0.0.1

// server.js
const http = require('http')
const fs = require('fs')

http.createServer(function (request, response) {
  console.log('request come', request.url)

  const html = fs.readFileSync('test.html', 'utf8') // 注意设置 utf8,这样读取的是字符串,否则是二进制的数据
  response.writeHead(200, {
    'Content-Type': 'text/html' // 不设置的话,浏览器会直接显示,不解析;默认浏览器会加上
  })
  response.end(html)
}).listen(8888)

console.log('server listening on 8888')
// server2.js
const http = require('http')

http.createServer(function (request, response) {
  console.log('request come', request.url)

  response.writeHead(200, { // 不设置这个头,浏览器还是会发送请求,并接收内容,浏览器检查head头,如果没有'Access-Control-Allow-Origin',并且设置为允许,浏览器会把本次请求返回的内容会略掉,并且报错。
    'Access-Control-Allow-Origin': 'http://127.0.0.1:8888', // 允许 8888 的域名访问,*也可以(不够安全)
  })
  response.end('123')
}).listen(8887)

console.log('server listening on 8887')

添加多个头

通过判断 request.url 来判断是否添加不同的 head 头。

JSONP

浏览器允许 link img script中的src或href进行跨域请求,JSONP的原理就是在script标签中,加载链接,链接访问了服务器某个请求,并返回了内容,服务器返回的内容是可控的,可以在服务器返回内容中的script标签中写一段可执行的JS代码,然后调用JSONP发起请求的一些内容。

// test.html
<script src="http://127.0.0.1:8887/"></script>

这样不设置8887的head头,也可以进行跨域,得到请求内容。

CORS跨域限制

主要包括 methods content-type 和 请求头的限制。

允许方法

默认允许方法 GET HEAD POST,其他的方法 PUT DELETE 默认是不允许的。

允许Content-Type

text/plain

multipart/form-data

application/x-www-form-urlencoded

除了这三种,其他的 Content-Type 也需要使用预请求验证后,才能发送。

其他限制

  • 请求头限制,自定义的请求头默认是不允许的,也需要验证;官方文档,关于请求头的详细信息https://fetch.spec.whatwg.org/#cors-safelisted-request-header
  • XMLHttpRequestUpload 对象均没有注册任何事件监听器(很少用)
  • 请求中没有使用 ReadableStream 对象(很少用)

CORS预请求

demo

8888下的 test.html 发送的请求携带了自定义请求头,从浏览器看请求发送成功,返回状态码200,但是浏览器会报错,不允许跨域,数据虽然返回,但被浏览器忽略了。

// server.js
const http = require('http')
const fs = require('fs')

http.createServer(function (request, response) {
  console.log('request come', request.url)

  const html = fs.readFileSync('test.html', 'utf8') 
  response.writeHead(200, {
    'Content-Type': 'text/html' 
  })
  response.end(html)
}).listen(8888)

console.log('server listening on 8888')
// server2.js
const http = require('http')

http.createServer(function (request, response) {
  console.log('request come', request.url)

  response.writeHead(200, { 
    'Access-Control-Allow-Origin': '*'
  })
  response.end('123')
}).listen(8887)

console.log('server listening on 8887')
<script>
  fetch('http://localhost:8887', { // 发送请求
    method: 'POST',
    headers: { // 一个自定义的头
      'X-Test-Cors': '123'
    }
  })
</script>

实现预请求

const http = require('http')

http.createServer(function (request, response) {
  console.log('request come', request.url)

  response.writeHead(200, { 
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Headers': 'X-Test-Cors' // 服务端添加允许自定义请求头
  })
  response.end('123')
}).listen(8887)

console.log('server listening on 8887')

查看network,会发现多了一个请求文件localhost,它的 Request Method 请求方法是 OPTIONS,其他的很正常请求一样,通过 OPTIONS 请求获得服务端允许发送请求的认可。之后再实际发送 POST 请求。

允许其他请求方法

const http = require('http')

http.createServer(function (request, response) {
  console.log('request come', request.url)

  response.writeHead(200, {
    'Access-Control-Allow-Origin': '*', 
    'Access-Control-Allow-Headers': 'X-Test-Cors',
    'Access-Control-Allow-Methods': 'POST, PUT, DELETE' // 允许使用被限制的请求方法
  })
  response.end('123')
}).listen(8887)

console.log('server listening on 8887')

跨域请求时间

比如第一次请求,network观察文件,会有 Method 是 OPTIONS 的预请求文件,再次刷新网页发送请求,这个文件就不会再发送了,不会出现在 network 列表中。

const http = require('http')

http.createServer(function (request, response) {
  console.log('request come', request.url)

  response.writeHead(200, {
    'Access-Control-Allow-Origin': '*', 
    'Access-Control-Allow-Headers': 'X-Test-Cors',
    'Access-Control-Allow-Methods': 'POST, PUT, DELETE',
    'Access-Control-Max-Age': '1000' // 1000s之内,不需要再发送预请求进行验证了,时间内直接发正式请求
  })
  response.end('123')
}).listen(8887)

console.log('server listening on 8887')

浏览器希望通过限制保证服务端的安全

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值