HTTP之options预检请求

前置知识点

HTTP请求方法

简单请求

预检请求

  • 只有跨域的情况下,才会发生预请求
  • 与前述简单请求不同,“需预检的请求”要求必须首先使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。“预检请求”的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

withCredentials为true不会产生预请求

哪些情况下会产生预请求?

1. 请求头Content-Type为application/json会产生预请求

前端代码:

function run(){
            let xhr = new XMLHttpRequest()
            xhr.open('POST','http://127.0.0.1:8080/Public//testPost')
            xhr.setRequestHeader('Content-Type','application/json')
            xhr.onload = function(res){
                console.log(res)
            }
            xhr.send()
        }

        run()
复制代码

后端代码:

 public function testPost(){
        header("Access-Control-Allow-Headers: Content-Type");
        header("Access-Control-Allow-Origin: *");
        echoJsonResult(1,'',$_POST);
    }
复制代码

当后端没有配置Access-Control-Allow-Headers包含Content-Type,报错如下:

Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
复制代码

当后端没有配置Access-Control-Allow-Origin,报错如下

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
复制代码

浏览器发出的两次请求:

  • OPTIONS请求

image.png

image.png

image.png

  • POST请求

image.png

image.png

image.png

2. 设置了用户自定义请求头会产生预检请求

前端代码:

        let xhr = new XMLHttpRequest()
            xhr.open('POST','http://127.0.0.1:8080/Public//testPost')
            xhr.setRequestHeader('abc','123')
            xhr.onload = function(res){
                console.log(res)
        }
         xhr.send()
复制代码

后端代码:

     public function testPost(){
        header("Access-Control-Allow-Origin: *");
        header('Access-Control-Allow-Headers: abc');
        echoJsonResult(1,'',$_POST);
    }
复制代码

OPTIONS请求的request请求头

Access-Control-Request-Headers: abc
Access-Control-Request-Method: POST
复制代码

OPTIONS请求的response响应头

Access-Control-Allow-Headers: abc
Access-Control-Allow-Origin: *
复制代码

当后端没有配置Access-Control-Allow-Headers为abc时 ,报错如下

Request header field abc is not allowed by Access-Control-Allow-Headers in preflight response.
复制代码

CORS跨域

当请求跨域,后端没有配置时,报错如下

Access to XMLHttpRequest at 'http://127.0.0.1:8080/Public//testPost' from origin 'http://10.200.137.43:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
复制代码

则后端配置代码:

     public function testPost(){
        header("Access-Control-Allow-Origin: *");
        echoJsonResult(1,'',$_POST);
    }
复制代码

withCredentials为true时需要后端配置响应头Access-Control-Allow-Credentials为true (不会产生预请求)

前端代码:

         let xhr = new XMLHttpRequest()
            xhr.open('POST','http://127.0.0.1:8080/Public//testPost')
            xhr.withCredentials = true
            xhr.onload = function(res){
                console.log(res)
          }
          xhr.send()
复制代码

后端代码:

    public function testPost(){
        header("Access-Control-Allow-Origin: http://10.200.137.43:8080");
        header("Access-Control-Allow-Credentials: true");
        echoJsonResult(1,'',$_POST);
    }
复制代码

浏览器只发起一次POST请求:

image.png

image.png

image.png
当后端配置Access-Control-Allow-Origin为星号时,报错如下:

The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
复制代码

当后端没有配置Access-Control-Allow-Credential时,报错如下

The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
复制代码

参考链接

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享