跨域及前后端分离

最近总结了下常使用的跨域方案,希望对大家有用:

      因为浏览器的同源策略,浏览器实施安全限制,凡是发送请求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的支持,有两种实现方式:

  1. 配置方式
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">

    <property name="jsonpParameterNames">

        <set>

            <value>jsonp</value>

            <value>callback</value>

        </set>

    </property>

</bean>
  1. 继承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

前后端分离,目前想使用这种方式,还未实践

原文地址:https://www.cnblogs.com/fnncat/p/7085302.html