原文地址:http://blog.csdn.net/wangjun5159/article/details/49096445

错误信息:

XMLHttpRequest cannot load http://web.image.myqcloud.com/photos/v2/10008653/bhpocket/0/?sign=4FcLKd5B8…p4SkFVUEJtZ1omZT0xNDQ0NzExMDE5JnQ9MTQ0NDcwNzQxOSZyPTEzMDMyMDgzOTAmdT0wJmY9.No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

分析:

Access control allow origin直译过来就是"访问控制允许同源",这是由于ajax跨域访问引起的。所谓跨域就是,在a.com域下,访问b.com域下的资源;出于安全的考虑,浏览器允许跨域写,而不允许跨域读,写就是上行,发送请求,send request,读就是下行,接受响应,receive response;理解了这两条规则,以下现象我们也就能理解了;

1、表单默认提交(get、post)、超链接访问域外的资源,这是允许的,因为在点击按钮/超链接时,浏览器地址已经变了,这就是一个普通的请求,不存在跨域;

2、ajax(借助xmlhttprequest)跨域请求,这是被禁止的,因为ajax就是为了接受接受响应,这违背了,不允许跨域读的原则

3、jsonp属于跨域读且形式限制为GET方式,它利用了script标签的特性;这是允许的。因为浏览器把跨域读脚本,当作例外,类似的img、iframe的src都可以请求域外资源

解决方案:

方案1,给chrome浏览器添加参数,--disable-web-security

方案2

a,

非IE浏览器,利用xmlhttprequest,在request header添加origin:本域名地址,通常不需要手动添加,浏览器会动添加

IE浏览器,利用XDomainRequest发送请求,它会自动封装header中添加origin

b,response header添加access-control-allow-origin:*

跨域演示及代码

验证过程,首先访问http://本机ip:port/project_name/a.jsp,然后,a.jsp发送ajax请求,http://localhost:port/project_name/b.jsp,这样就产生了跨域的问题。

a.jsp

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
  4. <head>
  5. <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
  6. <title>跨域演示</title>
  7. <script type="text/javascript" src="jquery-1.11.2.js"></script>
  8. <script type="text/javascript" src="jquery.form.js"></script>
  9. </head>
  10. <script type="text/javascript">
  11. $(document).ready(function() {
  12. $.getJSON('http://localhost/test_maven/b.jsp', function(data) {
  13. alert("request succeed");
  14. });
  15. });
  16. </script>
  17. </body>

b.jsp

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%
  4. response.setHeader("Access-Control-Allow-Origin", "*");
  5. response.getWriter().write("hahahhaha");
  6. %>

如果注释掉response.setHeader("Access-Control-Allow-Origin", "*");,那么就会出现access control allow origin错误;使用通配符*,允许所有跨域访问,所以跨域访问成功。

但是,请注意使用通配符*,会允许来自任意域的跨域请求访问成功,这是比较危险的,所以在生产环境通常会做更精确控制;

简单请求

上述请求是简单请求,只要添加了Access-Control-Allow-Origin:*,就会访问成功,如果是复杂请求,我们需要更进一步的处理,才能成功。这里先解释一下什么是简单请求和复杂请求。

  1. Simple requests
  2. A simple cross-site request is one that meets all the following conditions:
  3. The only allowed methods are:
  4. GET
  5. HEAD
  6. POST
  7. Apart from the headers set automatically by the user agent (e.g. Connection, User-Agent, etc.), the only headers which are allowed to be manually set are:
  8. Accept
  9. Accept-Language
  10. Content-Language
  11. Content-Type
  12. The only allowed values for the Content-Type header are:
  13. application/x-www-form-urlencoded
  14. multipart/form-data
  15. text/plain

简单来说,符合上述条件的都是“简单请求”,除了简单请求就是“复杂请求”。

复杂请求

在正式post之前,浏览器会先发出一个options请求(也叫preflight),同时header带上origin还有Access-Control-Request-*:**之类的头,服务器响应会返回相应的access-control-allow-origin,如果匹配,那么浏览器就会发送正式post,否则就会出现上述错误。这也解答了,跨域访问时,我们明明发送的post请求,失败的话,查看chrome network会发现是options方法的原因。

根据上述过程,后台方法额外需要options方法,以下是测试样例。

这里的content-type不属于(application/x-www-form-urlencoded,multipart/form-data,text/plain)中的任何一种,所以是复杂请求。

  1. $.ajax({
  2. type: "post",
  3. url: "http://localhost/test_maven/a_action",
  4. contentType: "application/json",
  5. dataType:  "json",
  6. success: function(){
  7. alert("request succeed");
  8. }
  9. });
  1. @RequestMapping(value = "/a_action",
  2. method=RequestMethod.OPTIONS)
  3. public void aActionOption(HttpServletResponse response ) throws IOException{
  4. System.out.println("option execute.....");
  5. response.setHeader("Access-Control-Allow-Headers", "accept, content-type");
  6. response.setHeader("Access-Control-Allow-Method", "POST");
  7. response.setHeader("Access-Control-Allow-Origin", "http://192.168.8.36");
  8. }
  1. @RequestMapping(value = "/a_action",method=RequestMethod.POST)
  2. public void aAction(HttpServletResponse response ) throws IOException{
  3. System.out.println("a_action execute.....");
  4. }

第一次是options请求,http options请求跟get、post、head等一样,都属于http的请求方法,options方法,用来获取服务器端某url支持的方法,response header中allow标志支持的方法

第二次才是真正的请求

这个方案是利用了w3c的最新规范,所以该方案依赖浏览器的实现。

总结:

出现Access control allow origin错误,说明是跨域请求失败!浏览器发送请求成功,同时浏览器也接收到响应了,但是限制了XmlHttpRquest接收请求,不会让xmlhttprequest接受到响应,并且在js控制台报错。这也就是我们在网络控制台(Network)能看见http 状态码是200,但是在js控制台(Console)出现js错误的原因。

Access control allow origin 简单请求和复杂请求的更多相关文章

  1. 解决js ajax跨越请求 Access control allow origin 异常

    // 解决跨越请求的问题 response.setHeader("Access-Control-Allow-Origin", "*");

  2. 跨域请求错误: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource

    今天在学习Angular 的HttpInterceptor 拦截器时,发现添加了新的headers键值之后总是报跨域错误.后台使用的是asp.net core. 检查发现,在添加了新的header之后 ...

  3. SELINUX、Security Access Control Strategy && Method And Technology Research - 安全访问控制策略及其方法技术研究

    catalog . 引言 . 访问控制策略 . 访问控制方法.实现技术 . SELINUX 0. 引言 访问控制是网络安全防范和客户端安全防御的主要策略,它的主要任务是保证资源不被非法使用.保证网络/ ...

  4. Linux VFS Extended Attribute And Access Control Table

    catalog . 简介 . 扩展属性 . 访问控制表 . 小结 0. 简介 许多文件系统都提供了一些特性,扩展了VFS层提供的标准功能,虚拟文件系统不可能为所有特性都提供具体的数据结构.超出标准的U ...

  5. Security Access Control Strategy && Method And Technology Research - 安全访问控制策略及其方法技术研究

    1. 访问控制基本概念 访问控制是网络安全防范和客户端安全防御的重要基础策略,它的主要任务是保证资源不被非法使用.保证网络/客户端安全最重要的核心策略之一. 访问控制包括 入网访问控制 网络权限控制 ...

  6. 基于角色的权限控制系统(role-based access control)

    role-based access control(rbac),指对于不同角色的用户,拥有不同的权限 .用户对应一个角色,一个角色拥有若干权限,形成用户-角色-权限的关系,如下图所示.当一个用户进行访 ...

  7. 介质访问控制子层-Medium Access Control Sublayer:多路访问协议、以太网、无线局域网

    第四章 介质访问控制子层-Medium Access Control Sub-layer 4.1介质访问控制子层概述 MAC子层不属于之前提到的OSI或TCP/IP架构的任何一层,这也是为什么这一层被 ...

  8. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' heade

    XMLHttpRequest cannot load http://10.164.153.37:8050/WebService/WebService.asmx/wsGetStreetData. Res ...

  9. RBAC(Role-Based Access Control,基于角色的访问控制)

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角色- ...

随机推荐

  1. BZOJ 5427: 最长上升子序列

    $f[i] 表示长度为i的最长上升子序列的最后一位的最小值是多少$ 对于普通的$LIS我们可以二分确定位置去更新$ 再来考虑对于这个,如果有某一位没有确定的话 那么这一位是可以随便取的,也就是说,所有 ...

  2. php面向对象类中常用的魔术方法

    php面向对象类中常用的魔术方法   1.__construct():构造方法,当类被实例化new $class时被自动调用的方法,在类的继承中可以继承与覆盖该方法,例: //__construct( ...

  3. HashMap,HashTable,ConcorrentHashMap的线程方式

    1.HashMap不是线程安全的,put,resize 2.HashTable是线程安全的,synchronized,但是效率较低 3.ConcorrentHashMap 对HashMap的一种加线程 ...

  4. saltstack之keepalived的安装配置

    使用saltstack编译安装keepalived: 创建相应的目录,并在目录下创建相应的sls配置文件 [root@node1 ~]# mkdir /srv/salt/prod/keepalived ...

  5. 20145324 《Java程序设计》第6周学习总结

    20145324 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 1.使用输入串流将数据从来源取出 InputStream 使用输出串流将数据写入目的地 OutStream ...

  6. 20135302魏静静——linux课程第六周实验及总结

    linux课程第六周实验及总结 实验及学习总结 1.进程描述符task_struct数据结构 进程的作用: 将信号.进程间通信.内存管理和文件系统联系起来 操作系统的三大功能: 进程管理.内存管理.文 ...

  7. JavaScript中字符操作之大小写转换

    1.toUpperCase()   方法用于把字符串转换为大写 var str = prompt("请输入需转换大写的字符串:"); str = str.toUpperCase() ...

  8. 百度console输出

    try{ if(window.console&&window.console.log) { console.log("一张网页,要经历怎样的过程,才能抵达用户面前?\n一位新 ...

  9. ubuntu 18.04在更新软件库时出现E: Release file for http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease is not valid yet...

    1.完整的错误信息如下: E: Release file for http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease i ...

  10. valid 校验方式

    校验参数方法:1.最简单的方式是,使用Java bean注解校验(如 @NotEmpty...)2.适合复杂点的自定义校验(推荐) 2.1 先定义一个校验接口: public interface Va ...