因为面向互联网的性质,我们公司的大部分系统都采用多子域的方式进行开发和部署,以达到松耦合和分布式的目的,因此子系统间的交互不可避免。虽然通过后台的rpc框架解决了大部分的交互问题,但有些情况下,前端直接发起的各子系统之间交互仍然不可避免。由于浏览器天然的安全性本质,早期通常是不允许直接调用不同域名下的请求。如果直接调用不同域下的请求,会报“No 'Access-Control-Allow-Origin' header is present on the requested resource”错误。

所以在HTML 5以前,都是变相的方式绕过,主要有如下几种方式:

JSONP

我们发现,Web页面上调用js文件时不受是否跨域的影响,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>。那就是说如果要跨域访问数据,就服务端只能把数据放在js格式的文件里。恰巧我们知道JSON可以简洁的描述复杂数据,而且JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。然后客户端就可以通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件。客户端在对JSON文件调用成功之后,也就获得了自己所需的数据。这就形成了JSONP的基本概念。允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

在angularjs中,通常是如下:

$http.jsonp(url + "?callback=JSON_CALLBACK") .success(function(data) {
 将data赋值给$scope的某些属性
});

但JSONP只支持get,这样就限制了传递的数据量。所以就有了HTML 5里面的CORS。

CORS

Cross-Origin Resource Sharing (CORS) 是W3c工作草案,它定义了在跨域访问资源时浏览器和服务器之间如何通信。CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。CORS规范简单地扩展了标准的XHR对象,以允许JavaScript发送跨域的XHR请求。它会通过
预检查(preflight)来确认是否有权限向目标服务器发送请求。

CORS与JSONP相比,更为先进、方便和可靠。

1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。如下:


对一个简单的请求,没有自定义头部,要么使用GET,要么使用POST,它的主体是text/plain,请求用一个名叫Orgin的额外的头部发送。Origin头部包含请求页面的头部(协议,域名,端口),这样服务器可以很容易的决定它是否应该提供响应。
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。
Header set Access-Control-Allow-Origin *

对于springboot(没有前置nginx时),可以如下配置:

    private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1允许任何域名使用
corsConfiguration.addAllowedHeader("*"); // 2允许任何头
corsConfiguration.addAllowedMethod("*"); // 3允许任何方法(post、get等)
return corsConfiguration;
} @Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}

为了防止XSS攻击我们的服务器, 我们可以限制域,比如在nginx中可以如下设置:

http {
......
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
......
}

具体参见https://michielkalkman.com/snippets/nginx-cors-open-configuration.html

上述都配置了,nginx报“

2019/01/24 16:14:20 [error] 18728#24984: *67 access forbidden by rule, client: 127.0.0.1, server: localhost, request: "OPTIONS /tabase/taprocess/diagram/loadAllNodeState.json?instanceId=20190121_aop_1 HTTP/1.1", host: "localhost"”,客户端报:

Failed to load http://localhost/tabase/taprocess/diagram/loadAllNodeState.json?instanceId=20190121_aop_1: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8086' is therefore not allowed access.

此时请求在nginx就出错了,因为nginx在windows,所以不是权限的问题。

解决方法:

增加如下:

         limit_except GET POST OPTIONS {
deny all;
}
或者去掉limit_except

Failed to load http://localhost/tabase/taprocess/diagram/loadAllNodeState.json?instanceId=20190121_aop_1: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values '*, http://localhost:8086', but only one is allowed. Origin 'http://localhost:8086' is therefore not allowed access.

nginx和后台同时包含了跨域处理,去掉一个即可。

Failed to load http://localhost/tabase/taprocess/diagram/loadAllNodeState.json?instanceId=20190121_aop_1: Response to preflight request doesn't pass access control check: 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'. Origin 'http://localhost:8086' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

因为使用了下列选项:

xhrFields: {
withCredentials: true
},

不能使用*。

jquery.min.js:5 Failed to load http://localhost/tabase/taprocess/diagram/loadAllNodeState.json?instanceId=20190121_aop_1: Response to preflight request doesn't pass access control check: 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'. Origin 'http://localhost:8086' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

增加

add_header Access-Control-Allow-Credentials true;

Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

在Access-Control-Allow-Headers增加所有的头类型,例如:

add_header Access-Control-Allow-Headers Origin,X-Requested-With,Content-Type,Accept;

所以使用nginx的完整配置如下(配置nginx,就去掉tomcat的cors):

        location ^~ /tabase/ {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,Content-Type,Accept;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
add_header Access-Control-Allow-Credentials true;
#root html;
#index testssl.html index.html index.htm;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.20.39.223:38080;
}
# 注意,不要limit_except选项

在angularjs中,我们可以如下调用cors请求:

myApp.config(function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
});
myApp.controller("JsonController",function($scope,$http) {
$scope.getAjax = function(url) {
$http.get(url).success(function (response) {
$scope.students = response;
});
};
});

nginx/ajax跨子域请求的两种现代方法以及403解决的更多相关文章

  1. ajax跨子域请求的两种现代方法

    因为面向互联网的性质,我们公司的大部分系统都采用多子域的方式进行开发和部署,以达到松耦合和分布式的目的,因此子系统间的交互不可避免.虽然通过后台的rpc框架解决了大部分的交互问题,但有些情况下,前端直 ...

  2. ASP.NET MVC 实现AJAX跨域请求的两种方法

    通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据的加载,例如Google. 在ASP.NET MVC 框 ...

  3. PHP允许AJAX跨域请求的两种方法

    * 一. 服务端设置 header 头允许AJAX跨域 ** 代码如下: // 允许 ityangs.net 发起的跨域请求 header("Access-Control-Allow-Ori ...

  4. AJAX跨域请求json数据的实现方法

    这篇文章介绍了AJAX跨域请求json数据的实现方法,有需要的朋友可以参考一下 我们都知道,AJAX的一大限制是不允许跨域请求. 不过通过使用JSONP来实现.JSONP是一种通过脚本标记注入的方式, ...

  5. GET和POST是HTTP请求的两种基本方法,区别是什么!?

    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...

  6. Ajax跨域问题的两种解决方法

    浏览器不允许Ajax跨站请求,所以存在Ajax跨域问题,目前主要有两种办法解决. 1.在请求页面上使用Access-Control-Allow-Origin标头. 使用如下标头可以接受全部网站请求: ...

  7. vue 使用axios 出现跨域请求的两种解决方法

    最近在使用vue axios发送请求,结果出现跨域问题,网上查了好多,发现有好几种结局方案. 1:服务器端设置跨域 header(“Access-Control-Allow-Origin:*”); h ...

  8. ASP.NET MVC 实现AJAX跨域请求方法《1》

    ASP.NET MVC 实现AJAX跨域请求的两种方法 通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据 ...

  9. ASP.NET MVC 实现 AJAX 跨域请求

    ASP.NET MVC 实现AJAX跨域请求的两种方法 和大家分享下Ajax 跨域的经验,之前也找了好多资料,但是都不行,后来看到个可行的修改了并测试下 果然OK了   希望对大家有所帮助! 通常发送 ...

随机推荐

  1. 教程 | 如何使用纯NumPy代码从头实现简单的卷积神经网络

    Building Convolutional Neural Network using NumPy from Scratch https://www.linkedin.com/pulse/buildi ...

  2. Word文档中的格式标记大全

    在Word中有很多的格式设置,很多格式设置都会有一些标记,这些标记是隐藏的,在打印文档时是不会打印出来的,但是它们却起着结构化文档的大作用.如果你在编辑文档,不妨点击格式标记开关,看看都有哪些格式标记 ...

  3. Cable master---poj1064(二分|卡精度)

    题目链接:http://poj.org/problem?id=1064 题意:有n条绳子,长度为Li,现在从这n条绳子中切割出K条相等的绳子,问切割出来的这k条绳子的最大长度为多少: 二分判断即可: ...

  4. JS闭包中的循环绑定处理程序

    前几天工作中写前端js代码时,遇到了遍历元素给它添加单击事件.就是这个问题让我整整调了一个下午.最后还是下班回家,上网查资料才知道怎么解决的. (PS:之前也在<jQuery基础教程>第四 ...

  5. BUG笔记:Win8 IE10下input[type="password"]内字符显示被截取问题

    这个BUG发生的截图: 这是发生在Windows8 IE10下,type为password的input文本框内输入长串字符后,初次失去焦点的时候会发生的一个BUG. 发生BUG的原因是这个文本框上应用 ...

  6. 修改lastpass主密码后需重启firefox才能加载已保存的站点密码或用导入工具

    最近索尼事件闹得沸沸扬扬,预防黑客先从升级密码开始.由于开发的需要一般是用firefox作为默认的浏览器,很早以前就装了lastpass密码管理器作为必备附加组件,在注册时按一下Alt+G就会帮你生成 ...

  7. Ubuntu Kylin 14.04 安装配置 jdk、eclipse、tomcat 通用

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq1053781225/article/details/24810107 一.安装jdk       ...

  8. query:callback

    function getName(callback) { setTimeout(function() { callback('Aaron') }, 1000) } //等待callback回调 get ...

  9. C#基础笔记(第十一天)

    1.复习字符串(1)字符串的不可变性(2)字符串的方法:1)Split() 分割 把字符串中不想要的内容分割掉 返回一个字符串类型的数组 可以添加StringSplitOption.RemoveEmp ...

  10. Saving Princess claire_(hdu 4308 bfs模板题)

    http://acm.hdu.edu.cn/showproblem.php?pid=4308 Saving Princess claire_ Time Limit: 2000/1000 MS (Jav ...