cors跨域

cors(Cross-Origin Resource Sharing),跨域资源共享

基于安全的考虑浏览器实施了同源策略,但是由于跨域访问资源的不可避免,w3c又指定了cors标准来实现跨域资源的访问

cors通信过程中浏览器会自动完成,若请求是跨域的,浏览器会自动在请求头中添加一些字段,所以要实现cors跨域只需要在服务端进行相应字段的设置

 

简单请求

1.get,post,head

2.http请求头中,除了自动设置的字段外,允许人为设置的字段只能是以下几个字段

  1)Accept

  2)Accept-Language

  3)Content-Language

  4)Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

符合以上俩个条件的就是简单请求(详细内容可以在MDN中查看)

 

复杂请求

复杂请求就是非简单请求,可能会对服务器数据产生副作用的请求。

首先浏览器会自动使用options方法发起一个预检请求,询问服务器是否允许该跨域请求,若允许则发起正式的请求

 

cors相关字段

1.Access-Control-Allow-Origin(必须)

  该字段的值表示允许访问服务器资源的域

  若允许任意域的请求则可以设置为‘*’

2.Access-Control-Allow-Methods

  请求允许的方法

3.Access-Control-Allow-Headers

  请求允许携带的首部字段

4.Access-Control-Allow-Credentials

  表示是否允许发送Cookie,值为true表示请求时可以携带cookie

5.Access-Control-Max-Age

  预检请求的结果能缓存的时长,单位为秒

 

实现cors跨域

1.用node.js开启俩个服务器,web.js和server.js

2.web.js监听3001端口,该服务器中有一个index.html

3.server.js监听3000端口,该服务器中有一个a.html

4.在index.html中点击按钮触发ajax请求去访问a.html,该请求跨域

web.js

var http = require('http')
var fs = require('fs')

var server = http.createServer()

server.on('request', function (req, res) {
  if (req.url === '/index.html') {
    fs.readFile('./index.html', 'utf-8', function (err, data) {
      res.end(data)
    })
  }
})

server.listen(3001, function () {
  console.log('server is open')
})

在web.js同一目录下创建index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="context"></div>
  <p>当前域为http://localhost:3001</p>
  <button onclick="login()">
    访问http://localhost:3000中的资源a.html
  </button>

  <script>
    function login () {
      var dom = document.getElementById('context')
      var xml = new XMLHttpRequest()
      xml.open('get', 'http://localhost:3000/a.html')
      xml.onreadystatechange = function () {
        if (xml.readyState === 4 && xml.status === 200) {
          dom.innerHTML = xml.responseText
        }
      }
      xml.send()
    }
  </script>
</body>
</html>

server.js

var http = require('http')
var fs = require('fs')

var server = http.createServer()

server.on('request', function (req, res) {
 // 允许访问本服务器的的域
  var allowOrigins = ['http://localhost:3001', 'http://localhost:3002']
  if (allowOrigins.includes(req.headers.origin)) {
  // 设置允许的域
    res.setHeader('Access-Control-Allow-Origin', req.headers.origin)
  if (req.url === '/a.html') {
      fs.readFile('./a.html', 'utf-8', function (err, data) {
        res.end(data)
      })
    }
  }
})

server.listen(3000, function () {
  console.log('server is open')
})

在server.js同一目录下创建a.html

<div>
  server中的资源
</div>

 

服务器都开启后,在浏览器地址栏输入http://localhost:3001/index.html

cors跨域java cors跨域配置_字段

点击按钮进行ajax请求

 

cors跨域java cors跨域配置_字段_02

可以看到跨域请求成功

在index.html中加一行代码,给请求头添加一个字段,让请求变成复杂请求

xml.setRequestHeader('Content-Type', 'application/json')

同时还要在服务端设置允许添加该首部字段

res.setHeader('Access-Control-Allow-Headers', 'Content-Type')

重启服务器,刷新页面后再次点击按钮发起ajax请求

 

cors跨域java cors跨域配置_字段_03

可以看到因为是复杂请求,所以一开始先进行了options预检请求,然后才是正式的请求

(在谷歌浏览器中可能是因为某些默认的浏览器设置,导致看不到options请求,截图中的结果是在火狐浏览器中查看的)