跨域访问-预请求及跨域常见问题

预请求

参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#预请求

简而言之,在跨域并且尝试添加一些特殊头及自定义头的情况下,由于浏览器的安全机制,会加多一次OPTIONS预请求(询问请求),与跨域服务器协商可以设置的头部信息,可以允许的HTTP协议等等信息。

以如下图一次跨域请求为例。

图中代码如下

 1 var settings = {
 2     type: "POST",
 3     url: 'http://www.movesun.com/cors.php?allow_method=PUT',
 4     contentType: "application/json",
 5     dataType:"json",
 6     data : {
 7         "name" : "lvyahui"
 8     },
 9     xhrFields : {
10         // withCredentials : true
11     },
12     success: function(resp) {
13         console.log(resp);
14     }
15     ,
16     headers: {
17         appkey:"87a8ea08-dbaa-11e6-b3f9-7056818a4db5",
18         "X_forwarded-for":"10.104.239.XXX"
19     }
20 };
21 $.ajax(settings);

可以看到,这段代码在movesun.com网站下,尝试向www.movesun.com发送跨域POST 请求,并且有自定义头(Content-Type设置了application/json类型也是原因之一),因此浏览器在发送真实post请求之前,发起了一个OPTIONS请求询问。

请求之所以可以成功,是因为后端服务器正常处理了OPTIONS请求,并且响应了正确的跨域响应头,后端代码cors.php如下

 1 <?php
 2 
 3 if('OPTIONS' ===  $_SERVER['REQUEST_METHOD']){
 4     header('Access-Control-Allow-Origin:*');
 5     header('Access-Control-Allow-Headers:appkey,X_forwarded-for,Content-Type');
 6     header('Access-Control-Allow-Methods:' . (isset($_GET['allow_method']) ? $_GET['allow_method'] : 'OPTIONS'));
 7     //header('Access-Control-Allow-Credentials:true');
 8     exit(0);
 9 }
10 
11 header('Access-Control-Allow-Origin:*');
12 
13 echo json_encode(array(
14     'code'  =>  0,
15     'msg'   =>  '',
16     'data'  =>  array()
17 ));exit(0);

可以看到服务器判断请求类型为OPTIONS时,指定了如下几个Http响应头

1、Access-Control-Allow-Origin  : 跨域服务器允许的来源地址(跟请求的Origin进行匹配),可以是*或者某个确切的地址,不允许多个地址。当然后台代码可以动态判断来源地址进行动态设置,这主要是因为有时需要允许任意来源访问,并且要携带Cookie,此时需要明确指定地址(原因在文后常见问题中说明),下面这段PHP代码和Java代码(注意Java代码中Cookie没有取端口,因为Cookie端口不同也算同域,可以访问到)就是取来源地址并响应

 1 if (isset($_SERVER['HTTP_REFERER'])) {
 2     $urls = parse_url($_SERVER['HTTP_REFERER']);
 3     $url = $urls['scheme'] . '://' . $urls['host'];
 4     if (isset($urls['port'])) {
 5         $url .= ':' . $urls['port'];
 6     }
 7 } else {
 8     $url = '*';
 9 }
10 
11 header("Access-Control-Allow-Origin: " . $url);
 1 public void filter(ContainerRequestContext requestContext) throws IOException {
 2     String origin = requestContext.getHeaderString("Origin");
 3     if(origin != null && !origin.trim().equals("")
 4             // postMan 请求的protocol 是 chrome-extension://
 5             && origin.startsWith("http://")){
 6         URL url  = new URL(origin);
 7         String strUrl = url.getProtocol() + "://" + url.getHost();
 8         if(url.getPort() > 0){
 9             strUrl += ":" + url.getPort();
10         }
11         originUrl = strUrl;
12         if(!cookieDomainAuto
13                 && (sysConfig.getCookieDomain() == null || sysConfig.getCookieDomain().equals(""))){
14             cookieDomainAuto = true;
15         }
16         if(cookieDomainAuto){
17             // 动态判断 cookie domain
18             if(url.getHost().matches(PATTERN_IP)){
19                 // IP
20                 sysConfig.setCookieDomain(url.getHost());
21             } else {
22                 int start = url.getHost().lastIndexOf('.',url.getHost().lastIndexOf('.') - 1);
23                 String domain;
24                 if(start > 0){
25                     domain = url.getHost().substring(start + 1);
26                 }else{
27                     domain = url.getHost();
28                 }
29                 // domain
30                 sysConfig.setCookieDomain(domain);
31             }
32         }
33     }
34 }
Java动态设置Allow-Origin与Cookie Domain

2、Access-Control-Allow-Methods:跨域服务器允许的请求方法。经测试发现,不论Access-Control-Allow-Methods设置为简单请求还是复杂请求类型,所有的简单的请求(GET,HEAD,POST)也是可以正常请求的。

3、Access-Control-Allow-Headers:跨域服务器允许客户端添加或自定义哪些http 头。

下面是这两次请求的报文

OPTIONS请求报文

 1 OPTIONS http://www.movesun.com/cors.php HTTP/1.1
 2 Host: www.movesun.com
 3 Proxy-Connection: keep-alive
 4 Pragma: no-cache
 5 Cache-Control: no-cache
 6 Access-Control-Request-Method: POST
 7 Origin: http://movesun.com
 8 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36
 9 Access-Control-Request-Headers: appkey, content-type, x_forwarded-for
10 Accept: */*
11 Referer: http://movesun.com/
12 Accept-Encoding: gzip, deflate, sdch
13 Accept-Language: zh-CN,zh;q=0.8
14 
15 
16 HTTP/1.1 200 OK
17 Date: Fri, 10 Mar 2017 05:48:07 GMT
18 Server: Apache
19 Access-Control-Allow-Origin: *
20 Access-Control-Allow-Headers: appkey,X_forwarded-for,Content-Type
21 Access-Control-Allow-Methods: POST
22 Vary: User-Agent,Accept-Encoding
23 Content-Encoding: gzip
24 Content-Length: 20
25 Content-Type: text/html
26 X-Cache: MISS from SK-SQUIDDEV-11
27 X-Cache-Lookup: MISS from SK-SQUIDDEV-11:8080

POST请求报文

 1 POST http://www.movesun.com/cors.php HTTP/1.1
 2 Host: www.movesun.com
 3 Proxy-Connection: keep-alive
 4 Content-Length: 12
 5 Pragma: no-cache
 6 Cache-Control: no-cache
 7 Origin: http://movesun.com
 8 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36
 9 Content-Type: application/json
10 Accept: application/json, text/javascript, */*; q=0.01
11 X_forwarded-for: 10.104.239.194
12 appkey: 87a8ea08-dbaa-11e6-b3f9-7056818a4db5
13 Referer: http://movesun.com/
14 Accept-Encoding: gzip, deflate
15 Accept-Language: zh-CN,zh;q=0.8
16 name=lvyahui

从报文中可以看出,OPTIONS请求后台可以拿到URL中的GET参数,也就是说,如果真实请求是GET请求,则后端在处理来询问的OPTIONS请求时,就可以获取到所有查询参数了。如mozilla官网所写,笔者调试发现,一些跨域请求,即便抛出了错误的情况下,请求也真的到了后台服务器,只是响应被浏览器拦截了。

另外,有时不想在后台代码中处理OPTIONS请求,则可以在nginx server节点下做如下配置,表示拦截处理所有OPTIONS请求。

 1 location ^~ / {
 2     if ($request_method = OPTIONS ) {
 3         add_header Content-Length 0;
 4         add_header Content-Type text/plain;
 5         add_header 'Access-Control-Allow-Origin' '*';
 6         add_header 'Access-Control-Allow-Methods' '*';
 7         add_header 'Access-Control-Allow-Headers' 'appkey,X_forwarded-for,Content-Type';
 8         return 200;
 9     }
10 }

 

常见跨域问题

下面是一些跨域下常见的一些问题

  • 添加了跨域服务器不允许的自定义头会抛出 XMLHttpRequest cannot load http://www.movesun.com/cors.php. Request header field custom_heaer is not allowed by Access-Control-Allow-Headers in preflight response.
  • 当未设置允许某种复杂请求时,使用复杂请求就会抛出如下错误,表示真实请求使用了服务器不允许的方法。在只允许POST的情况下,GET请求是可以被发送的,HEAD也可以成功,仅仅允许GET的情况下,POST也是可以发送成功的,HEAD也可以成功 。简单请求都可以成功,等等,其实经测试发现,不论Access-Control-Allow-Methods设置为简单请求还是复杂请求类型,所有的简单的请求(GET,HEAD,POST)也是可以正常请求的。XMLHttpRequest cannot load http://www.movesun.com/cors.php. Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.
  • 预处理请求没有没正常处理,这种是询问请求响应了非200状态码,会抛出 XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. Response for preflight has invalid HTTP status code 405 。如  
  • 1 if('OPTIONS' ===  $_SERVER['REQUEST_METHOD']){
    2     header("HTTP/1.1 405 Method Not Allowed");
    3     exit(-1);
    4 }

     

  • 错误是来源地址不是服务器所允许的来源地址。如下,此时服务器响应 Access-Control-Allow-Origin:http://www.movesun.com,表示跨域服务器允许在Origin:http://www.movesun.com 的机器上访问,而用户试图在http://movesun.com跨域请求目的服务器http://movesun.qq.com/cors.php?allow_method=PUT:XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://www.movesun.com' that is not equal to the supplied origin. Origin 'http://movesun.com' is therefore not allowed access.
  • 前端设置了携带签名标志,但是跨域服务器不允许携带,没有设置 Access-Control-Allow-Credentials:true 。如:XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://movesun.com' is therefore not allowed access.
  • 前端尝试在真实请求中携带签名Cookie,跨域服务器允许携带Cookie,但是服务器允许所有来源地址,会报这个错误,在跨域携带cookie时,必须明确指定来源地址,比如 Access-Control-Allow-Origin:http://movesun.com。例如:XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://movesun.com' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
并且 跨域携带Cookie时,跨域服务器处理询问请求(OPTIONS)和真实请求,都必须响应明确的来源地址和允许携带cookie的标志。否则会报上面两种错误。当然很显然的两次响应的Allow-Origin都是一致的。如下
 1 if('OPTIONS' ===  $_SERVER['REQUEST_METHOD']){
 2     header('Access-Control-Allow-Origin:http://movesun.com');
 3     header('Access-Control-Allow-Headers:appkey,X_forwarded-for,Content-Type');
 4     header('Access-Control-Allow-Methods:' . (isset($_GET['allow_method']) ? $_GET['allow_method'] : 'OPTIONS'));
 5     header('Access-Control-Allow-Credentials:true');
 6     exit(0);
 7 }
 8 header('Access-Control-Allow-Origin:http://movesun.com');
 9 header('Access-Control-Allow-Credentials:true');
10 echo json_encode(array(
11     'code'  =>  0,
12     'msg'   =>  '',
13     'data'  =>  array()
14 ));exit(0);

 

注意:文中的测试接口 在 http://movesun.com/cors.php  或者 http://www.movesun.com/cors.php,感兴趣的读者可以用这个接口测试。

转载于:https://www.cnblogs.com/lvyahui/p/6530990.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371356.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql查询优化之一:mysql查询优化常用方式

一、为什么查询速度会慢&#xff1f; 一个查询的生命周期大致可以按照顺序来看&#xff1a;从客户端&#xff0c;到服务器&#xff0c;然后在服务器上进行解析&#xff0c;生成执行计划&#xff0c;执行&#xff0c;并返回结果给客户端。其中在“执行”阶段包含了大量为了检索…

修复Sonar中常见的Java安全代码冲突

本文旨在向您展示如何快速修复最常见的Java安全代码冲突。 它假定您熟悉代码规则和违规的概念以及Sonar如何对其进行报告。 但是&#xff0c;如果您以前从未听说过这些术语&#xff0c;则可以阅读Sonar Concepts或即将出版的有关Sonar的书 &#xff0c;以获取更详细的解释。 为…

理解ThreadLocal

ThreadLocal:线程本地存储&#xff0c;为每个线程都创建了变量的副本&#xff0c;线程在访问变量时&#xff0c;可以直接访问自己内部的副本变量。 理解几个概念&#xff1a; 在java中ThreadLocal是一个类。 ThreadMap是一个类&#xff0c; Thread类是线程类。 ThreadLocal…

抖音右上角一个小黄点是什么_抖音官方入驻视频号,释放了一个什么样的信号?...

专注视频号观察第 328 篇这几天&#xff0c;视频号生态新入驻了一个企业号&#xff0c;在圈里引起不少的轰动&#xff0c;因为这个号的名字叫做———抖音。这件事在圈里引发不少的轰动&#xff0c;很多人惊叹&#xff1a;“连抖音都来开视频号了&#xff0c;你还在等什么&…

资源包技巧和最佳实践

今天是资源捆绑日。 通常&#xff0c;这是Java中最著名的国际化机制&#xff08;i18n&#xff09;。 使用它应该很容易。 但是&#xff0c;在弄脏手时会出现许多小问题。 如果您有相同的想法&#xff0c;则此文章适合您。 基本 java.util.ResourceBundle定义了用于访问Java中翻…

springMvc-文件上传

赶时间&#xff0c;又在写垃圾博客&#xff0c;在心里给自己一耳巴 1.单文件上传 2.多文件上传 代码&#xff1a; 页面&#xff1a; <!DOCTYPE html><html><head><meta charset"UTF-8"><title>Insert title here</title></he…

c cuda 指定gpu_GPU并行编程:熟练使用CUDA C语言

【IT168 专稿】一个大任务通常可能被分解成许多可以一起处理的小任务&#xff0c;以便创建一个解决方案&#xff0c;这和粉刷房子的道理是一样的&#xff0c;在粉刷之前&#xff0c;假设你需要买5公升油漆和5把刷子&#xff0c;你可以自己一个人干完采购和粉刷的活&#xff0c;…

js中使用0 “” null undefined {}需要注意

注意&#xff1a;在js中0为空&#xff08;false&#xff09; &#xff0c;代表空的还有“”&#xff0c;null &#xff0c;undefined&#xff1b; 如果做判断if(&#xff01;上面的四种值)&#xff1b;返回均为false console.log(!null);// true console.log(!0);//true consol…

PhpStorm 10.0.3破解版下载

汉化破解版软件下载&#xff1a; http://pan.baidu.com/s/1geNO24r 密码: d5ci 这个汉化破解软件解决了大纲视图里空白的问题。 先安装腾讯电脑管家&#xff0c;然后安装这个软件&#xff0c;安装到最后提示有个文件有病毒已删除&#xff0c;点确定后正常使用。转载于:https://…

Jenkins:部署JEE工件

随着持续集成和持续交付的出现 &#xff0c;我们的构建被分为不同的步骤&#xff0c;以创建部署管道。 这些步骤中的一些步骤可以是例如编译和运行快速测试&#xff0c;运行慢速测试&#xff0c;运行自动验收测试或发布应用程序等。 部署流程的最后一步意味着将我们的产品&…

seafile 部署_Seafile开启webdav及读写性能测试

为什么要在seafile搞webdavSeafile 一直是一款可靠的文件同步web应用&#xff0c;经过个人测试&#xff0c;同一台机器上&#xff0c;seafile在传输文件时的速度比nextcloud要快&#xff08;可能也与php的设置有关系&#xff09;&#xff0c;这是seafile的优势。但是&#xff0…

Python--校园网爬虫记

查成绩&#xff0c;算分数&#xff0c;每年的综合测评都是个固定的过程&#xff0c;作为软件开发者&#xff0c;这些过程当然可以交给代码去做&#xff0c;通过脚本进行网络请求获取数据&#xff0c;然后直接进行计算得到基础分直接填表就好了&#xff0c;查成绩再手动计算既容…

Spring–添加SpringMVC –第1部分

欢迎来到本教程的第四部分。 在这一部分中&#xff0c;我们将使用Spring MVC编写控制器和视图&#xff0c;并考虑我们的REST模型。 我们必须做的第一件事&#xff0c;就是根据目前的情况制作一个Web应用程序。 我们将web / WEB-INF文件夹添加到我们的项目根目录。 在WEB-INF内创…

[Linux] 权限与指令间的关系

我们知道权限对于使用者帐号来说是非常重要的&#xff0c;因为他可以限制使用者能不能读取/创建/删除/修改文件或目录&#xff01; 在这一章我们介绍了很多文件系统的管理指令&#xff0c;第五章则介绍了很多文件权限的意义。在这个小节当中&#xff0c; 我们就将这两者结合起来…

access month函数用法_学会了这7个EXCEL日期函数技巧,老板再让你加班,你找我!...

日期函数&#xff0c;常用年月日&#xff0c;时分秒&#xff0c;星期&#xff0c;季度&#xff0c;求差值等&#xff0c;学会以下几个函数&#xff0c;老板再让你加班&#xff0c;你找我&#xff01;1、记录当前时间(不随系统时间变化)NOW()函数与数据有效性结合&#xff0c;记…

css样式表的选择器与分类

css 样式表的作用&#xff1a; 主要用于结构,样式与行为,CSS主要的作用就是美化网页的一个语言,它的特点: 1.结构与样式分离的方式,便于后期维护与改版; 2.样式定义精确到像素的级别; css样式表的结构&#xff1a;CSS 称为层叠样式表 用于给网页设置各种样式 css样式的语法由3部…

Spring 3.1缓存和@Cacheable

缓存在软件领域已经存在很长时间了。 它们是那些真正有用的东西之一&#xff0c;一旦您开始使用它们&#xff0c;您会想知道如果没有它们&#xff0c;您是如何相处的&#xff0c;所以似乎让Spring的家伙们只是在版本中向Spring核心添加缓存实现有点奇怪。 3.1。 我猜想以前没有…

pytorchyolov4训练_使用pytorch-yolov5 訓練自己的數據集-2020.6.15

make yolov5 pytorch train datasets训练所需环境 python3.5, pytorch1.3, torchvision 0.4.1 , tensorboard 1.14.0 , tensorflow-gpu1.14.0本例制作yolov5数据集 并进行数据训练从VOC数据集转为训练所需的coco数据集代码有待改进包含文件夹voc2coco/(Annotations/ JPEGImages…

meta 的作用 搜集

Meta标签中的format-detection属性及含义 format-detection翻译成中文的意思是“格式检测”&#xff0c;顾名思义&#xff0c;它是用来检测html里的一些格式的&#xff0c;那关于meta的format-detection属性主要是有以下几个设置&#xff1a;<meta name"format-detecti…

Web服务安全性和SOA路线图的人为维度

在大多数非平凡的SOA环境中&#xff0c;很难跟踪系统之间不断发展的集成&#xff0c;除非有明确的发布和查找适当信息的方法。 概述IT环境&#xff0c;定义当前或将要连接的内容&#xff0c;是维护环境的先决条件。 缺少这种情况通常会导致“面向意大利面条的环境”的感觉&…