ajax跨子域请求的两种现代方法
因为面向互联网的性质,我们公司的大部分系统都采用多子域的方式进行开发和部署,以达到松耦合和分布式的目的,因此子系统间的交互不可避免。虽然通过后台的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;
});
};
});
ajax跨子域请求的两种现代方法的更多相关文章
- nginx/ajax跨子域请求的两种现代方法以及403解决
因为面向互联网的性质,我们公司的大部分系统都采用多子域的方式进行开发和部署,以达到松耦合和分布式的目的,因此子系统间的交互不可避免.虽然通过后台的rpc框架解决了大部分的交互问题,但有些情况下,前端直 ...
- Ajax跨域问题的两种解决方法
浏览器不允许Ajax跨站请求,所以存在Ajax跨域问题,目前主要有两种办法解决. 1.在请求页面上使用Access-Control-Allow-Origin标头. 使用如下标头可以接受全部网站请求: ...
- ASP.NET MVC 实现AJAX跨域请求的两种方法
通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据的加载,例如Google. 在ASP.NET MVC 框 ...
- PHP允许AJAX跨域请求的两种方法
* 一. 服务端设置 header 头允许AJAX跨域 ** 代码如下: // 允许 ityangs.net 发起的跨域请求 header("Access-Control-Allow-Ori ...
- vue 使用axios 出现跨域请求的两种解决方法
最近在使用vue axios发送请求,结果出现跨域问题,网上查了好多,发现有好几种结局方案. 1:服务器端设置跨域 header(“Access-Control-Allow-Origin:*”); h ...
- AJAX跨域请求json数据的实现方法
这篇文章介绍了AJAX跨域请求json数据的实现方法,有需要的朋友可以参考一下 我们都知道,AJAX的一大限制是不允许跨域请求. 不过通过使用JSONP来实现.JSONP是一种通过脚本标记注入的方式, ...
- GET和POST是HTTP请求的两种基本方法,区别是什么!?
GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...
- Javascript跨域请求的几种解决方法
什么情况下才会出现跨域? 假设域名是:http://www.example.com.cn/ 如果所请求的域名跟这个域名不致,这种情况就是跨域,由于跨域存在漏洞,所以一般来说正常的跨域请求方式是请求不到 ...
- ASP.NET MVC 实现AJAX跨域请求方法《1》
ASP.NET MVC 实现AJAX跨域请求的两种方法 通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据 ...
随机推荐
- T-SQL 公用表表达式(CTE)
公用表表达式(CTE) 在编写T-SQL代码时,往往需要临时存储某些结果集.前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量.除此之外,还可以使用公用表表达式的方法.公用表表达式( ...
- “远程调试监视器(MSVSMON.EXE)似乎没有在远程计算机上运行“的完美解决方案
今天调试程序时,Visual Studio突然报出了如下错误: Microsoft Visual Studio 远程调试监视器(MSVSMON.EXE)似乎没有在远程计算机上运行.这可能是因为防火墙阻 ...
- URAL 1549 Another Japanese Puzzle(构造)
题目大意 构造一条闭合路线,使得路线不能相交,并且走直线的步数小于等于 S,转弯(左转和右转)的步数小于等于 T.(0≤S,T≤1000) 求一条最长的路线 做法分析 注意到,因为要求路线闭合,那么转 ...
- WebKit内核分析之FrameLoader
参考地址:http://blog.csdn.net/dlmu2001/article/details/6168545 FrameLoader类负责一个Frame的加载,在Frame的流程中起到非常重要 ...
- 解决linux crontab PHP fgetcsv 读取中文数据为空问题
公司一台服务器每天定时拉取媒体报告数据,发现每次获取的中文数据为空,发现下载下来的csv文件中文是正常的,手动再次执行一次发现是正常的 现在发现linux的默认地区是 "en_US.UTF- ...
- Flex Error #2156问题
出现这个问题是因为应用程序使用了特殊端口,修改端口就可以解决. 特殊端口列表 A security change has been made in Adobe Flash Player 9.0.115 ...
- 【转载】如何使用 gnome-screenshot 截图命令
转载自:http://www.linuxeden.com/html/softuse/20130726/141753.html 日常工作中,我们经常需要截取屏幕状态来给其他人看.一般情况下,我们能最直接 ...
- left join on
问题: select * from A left join f on e.cust=f.account_id where f.status='0' 与 select * from A left jo ...
- Deep Learning 在中文分词和词性标注任务中的应用
开源软件包 SENNA 和 word2vec 中都用到了词向量(distributed word representation),当时我就在想,对于我们的中文,是不是也类似地有字向量(distribu ...
- mysql-5.6.14-winx64免安装配置
MySQL5.6.11安装步骤(Windows7 64位) 1. 下载MySQL Community Server 5.6.14 2. 解压MySQL压缩包 将以下载的MySQL压缩包解压到自定义目录 ...