最近总结了下常使用的跨域方案,希望对大家有用:
因为浏览器的同源策略,浏览器实施安全限制,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。关于跨域问题,提供以下目前常用的解决方案:
一、 JSONP跨域请求
1) 简介
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。
2) 原理
Script的src 不受同源策略的限,JSONP将JSON请求封装进一个 JavaScript函数,作为脚本发回给浏览器。客户端加载时,该脚本不受限于同源策略,函数就像其中的JSON对象一样。
3) 使用方法
非统一框架项目
² 前端:
若使用非框架的前端,推荐使用jQuery本身封装在ajax中的jsonp请求方法,在success回调函数中可获取正常json数据体。
$.ajax({ url: 'http://192.168.95.248:18080/jsonp/testJsonp',//请求地址 dataType: "jsonp", jsonp: "callback", //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback) success: function (data) { console.log(data) } });
² 服务端:
SpringMVC 4.1开始加入了对JSONP的支持,有两种实现方式:
- 配置方式
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"> <property name="jsonpParameterNames"> <set> <value>jsonp</value> <value>callback</value> </set> </property> </bean>
- 继承AbstractJsonpResponseBodyAdvice,对controller做处理
@ControllerAdvice(basePackages = "com.github") public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() { super("callback", "jsonp"); } }
返回数据结构:
优缺点
- 优点:
兼容性好,适配绝大多数浏览器(保证兼容性IE8+),不需要XMLHttpRequest或ActiveX的支持;
- 缺点:
a) 只支持get请求而不支持post等其他类型的HTTP请求;
b) jsonp在调用失败的时候不会返回各种HTTP状态码;
c) 要确定jsonp的请求是否失败并不容易,大多数框架的实现都是结合超时时间来 判定;
二、Cors 前后端分离
1) 简介
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
2) 原理
CORS的基本原理是通过设置HTTP请求和返回中header,告知浏览器该请求是合法的,从而实现跨域。
3) 使用方法
² 前端:
发送cors请求 (已经在框架上对其进行封装,可直接使用)
cors: function (options) { //设置jquery 支持跨域 $.support && ($.support.cors = true); var config = $.extend({ type: 'post', dataType: 'json', crossDomain: true, contentType: "application/json; charset=utf-8", beforeSend: function (xhr) { xhr.overrideMimeType("text/plain; charset=utf-8"); }, xhrFields: { withCredentials: true } }, options); if ($.support && $.support.msie) { //为ie浏览器时增加xhrFields配置 config["xhrFields"] = { withCredentials: true }; } $.ajax(config); },
var corsConfig= { url: 'http://192.168.95.248:18081/test/hello4?page=1&size=10',//请求地址 type: 'get', //请求方式 dataType: 'json',//预期服务器返回的数据类型 contentType: "application/json; charset=utf-8",//发送信息至服务器时内容编码类型 beforeSend: function (xhr) { //在发送请求之前调用,并且传入一个 XMLHttpRequest 作为参数 xhr.overrideMimeType("text/plain; charset=utf-8"); } } ajax.cors(corsConfig);
IE8,9不兼容, withCredentials 特性在IE9及以下的版本也不会有实现。
解决IE8,IE9兼容的方法:
方案一:
兼容IE8,9的插件
https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest
- 缺点:
1.只能是GET 或是POST请求,在使用post时,数据总是发送一个 Content-Type 为text/plain,不能设置其他请求头部;
2.只能是HTTP或者HTTPS,并且双方的协议需要一致;
3.不支持Cookie的发送和接收;
4.无法读写返回头部;
方案二:
IE开启设置:
² 服务端:
3.1 配置文件
config/*.properties
web模块application.properties
3.2 启动类
加入CORS处理Filter
b),优缺点
优点:
CORS支持所有类型的HTTP请求,可以使用普通的ajax实现跨域。
缺点:
1, 存在兼容性问题,IE10及以上才可正常发送请求
2, Cookie携带问题,IE8,9用户手动设置浏览器,才可以支持正常的cookie发送和接受;
CORS本身协议支持IE8+ , Firefox5+, Chrome12+, Safari4+,移动端几乎全支持。但在较早版本(8 和 9)中,CORS 机制是借由 XDomainRequest 对象完成的,所以在IE8,9中也无法通过XmlHttpRequest2 的属性”withCredentials”携带cookie。
三、使用Nginx反向代理
1) 简介
nginx 是一个高性能的HTTP和反向代理服务器,特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。
2) 原理
Nginx可作为反向代理服务器把http请求转发到另一个或者一些服务器上,将本地一个url前缀映射到要跨域访问的web服务器上,也就是,将对后端请求映射到某一路径,然后在Nginx内配置将该路径的请求重写到真正的后端服务所在。就可以实现跨域访问。
3) 配置方法
跨域解决的方案:简易配置示例:
server {
listen 9980;
server_name localhost;
location / {
#前端页面地址
proxy_pass http://localhost:8892;
}
location ^~/apis {
rewrite ^/apis/(.*)$ /$1 break;
#后端服务地址
proxy_pass http://localhost:18081;
}
具体说明:
配置了一个/apis的拦截,把所有/apis/**的请求进行重写,比如/apis/hello4?page=1&size=12会重写到真正的后端服务地址http://localhost:18081/hello4?page=1&size=12,由于前后端都是在localhost: 9980下,就不存在跨域问题。
参考资源:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
https://stackoverflow.com/questions/10232017/ie9-jquery-ajax-with-cors-returns-access-is-denied
https://stackoverflow.com/questions/3362474/jquery-ajax-fails-in-ie-on-cross-domain-calls
l
前后端分离,目前想使用这种方式,还未实践