JavaScript跨域

JavaScript 跨域

出自:http://www.javashuo.com/article/p-mdkqrtyw-k.htmljavascript

1、請求路徑組成

協議://+[用戶名/密碼@]+主機+公司名+機構名+:端口+/路徑html

2、域名

主機+公司名+機構名java

3、域

協議://+主機+公司名+機構名+:端口jquery

4、什麼是跨域

由於JavaScript同源策略的限制,A域名下的JavaScript沒法操做B或是C域名下的對象,因此就出現跨域一詞;web

同源策略:ajax

請求的url地址,必須與瀏覽器上的url地址處於同域上,也就是域名,端口,協議相同。apache

因此跨域就是: 域名,端口,協議三者其一不一樣;json

5、實現跨域

5.一、JSONP跨域

5.1.一、javaScript實現JSONP跨域

JSONP跨域是利用script腳本容許引用不一樣域下的js實現的,將回調方法帶入服務器,返回結果時回調。跨域

@WebServlet(name = "JSONPServlet", urlPatterns = "/callback")
public class JSONPServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String callback =  request.getParameter("callback");
        System.out.println(callback);
        response.getWriter().write(callback+"('"+new Date().toLocaleString()+"')");
    }
}
服務器
<body>
        <h1>JSONP跨域</h1>
        <h2>JSONP跨域是利用script腳本容許引用不一樣域下的js實現的,將回調方法帶入服務器,返回結果時回調。</h2>
        <script type="text/javascript" src="js/jquery-1.11.3.js" ></script>
        <script type="text/javascript">
            var show = function ( data){
                window.alert(data);
            }
        </script>
        <script type="text/javascript" src="http://localhost:8080/callback?callback=show" charset="utf-8"></script>
    </body>
客戶端

結果:瀏覽器

     服務器返回一段javascript,經過指定的方法名調用。從圖中能夠看出,使用JSONP的形式調用已經再也不是經過XMLHTTPRequest對象,而是同步調用。

5.1.二、jQuery使用JSONP跨域

@WebServlet(name = "JSONPServlet", urlPatterns = "/callback")
public class JSONPServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String callback =  request.getParameter("callback");
        System.out.println(callback);
        response.getWriter().write(callback+"('"+new Date().toLocaleString()+"')");
    }
}
服務器
<script type="text/javascript" src="js/jquery-1.11.3.js" ></script>
        <script type="text/javascript">
            $("#cross_domain--button").click( function (){
                $.get("http://localhost:8080/callback?callback=?",function(data){
                    alert(data)
                }, "jsonp")
            });
        </script>
客戶端

 

在jQuery中若是使用JSONP只須要將返回數據類型設置爲jsonp就能夠了。

總結:

一、只支持get請求,不支持post請求;

二、請求是同步的;服務器返回數據要處理,要添加回調函數。

5.二、跨域資源共享(cors)

同源策略(same origin policy)的限制下非同源的網站之間不能發送 ajax 請求的。

w3c 提出了跨源資源共享CORS即Cross Origin Resource Sharing(跨域源資源共享),就是咱們所熟知的跨域請求。

跨域資源共享(CORS)是一種網絡瀏覽器的技術規範,它爲Web服務器定義了一種方式,容許網頁從不一樣的域訪問其資源。

CORS與JSONP相比:

一、 JSONP只能實現GET請求,而CORS支持全部類型的HTTP請求。

二、 使用CORS,開發者可使用普通的XMLHttpRequest發起請求和得到數據,比起JSONP有更好的錯誤處理。

三、 JSONP主要被老的瀏覽器支持,它們每每不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS。

四、CORS 將請求分爲兩類:簡單請求和非簡單請求:

5.2.一、簡單請求

/**
 * 實現CORS簡單跨域服務
 */
@WebServlet(name = "SimpleServlet", urlPatterns = "/simple")
public class SimpleServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //設置容許CORS的域名,若是是全部則使用*
        response.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8020");
        response.getWriter().write("{\"name\":\"Book\"}");
    }
}
服務器
<html>
    <head>
        <meta charset="UTF-8">
        <title>實現CORS簡單跨域</title>
    </head>
    <body>
        <script type="text/javascript" src="js/jquery-1.11.3.js" ></script>
        <script type="text/javascript">
            $.get("http://localhost:8080/simple", function(data) {
                console.log(data)
                $("body").text(data.name)
            },"json");
            //跨域Post請求
            $.post("http://localhost:8080/simple", function(data) {
                console.log(data.name)
            }, "json");
        </script>
    </body>
</html>
客服端

結果:

 

簡單請求的部分響應頭及解釋以下:

Access-Control-Allow-Origin(必含)- 不可省略,不然請求按失敗處理。該項控制數據的可見範圍,若是但願數據對任何人均可見,能夠填寫"*"。

Access-Control-Allow-Credentials(可選) – 該項標誌着請求當中是否包含cookies信息,只有一個可選值:true(必爲小寫)。若是不包含cookies,請略去該項,而不是填寫false。這一項與XmlHttpRequest2對象當中的withCredentials屬性應保持一致,即withCredentials爲true時該項也爲true;withCredentials爲false時,省略該項不寫。反之則致使請求失敗。

Access-Control-Expose-Headers(可選) – 該項肯定XmlHttpRequest2對象當中getResponseHeader()方法所能得到的額外信息。

5.2.二、複雜請求

如說你須要發送PUT、DELETE等HTTP動做,或者發送Content-Type: application/json的內容就須要使用複雜請求了。

最早發送的是一種"預請求",此時做爲服務端,也須要返回"預迴應"做爲響應。預請求其實是對服務端的一種權限請求,只有當預請求成功返回,實際請求才開始執行。預請求以OPTIONS形式發送,當中一樣包含域,而且還包含了兩項CORS特有的內容。

5.2.2.一、Servlet支持CORS

@WebServlet(name = "ComplexServlet", urlPatterns = "/complex")
public class ComplexServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //設置容許CORS的域名,若是是全部則使用*
        response.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8020");
        response.addHeader("Access-Control-Allow-Methods", "GET,HEAD,POST,TRACE,OPTIONS,PUT,DELETE");
        response.addHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept");
        response.addHeader("Access-Control-Allow-Credentials", "true");
        response.getWriter().write("{\"name\":\"Book\"}");
    }

    @Override
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
服務器
<html>
    <head>
        <meta charset="UTF-8">
        <title>實現CORS複雜跨域</title>
    </head>
    <body>
        <script type="text/javascript" src="js/jquery-1.11.3.js" ></script>
        <script type="text/javascript">
            $.ajax({
                type:"post",
                url:"http://localhost:8080/complex",
                contentType:"application/json;charset=utf-8",
                dataType:"json",
                success:function(data){
                    $("body").text(data.name);
                }
            });
        </script>
    </body>
</html>
客戶端

 

Access-Control-Allow-Origin(必含) – 和簡單請求同樣的,必須包含一個域,不能是*號

Access-Control-Allow-Methods(必含) – 這是對預請求當中Access-Control-Request-Method的回覆,這一回復將是一個以逗號分隔的列表。儘管客戶端或許只請求某一方法,但服務端仍然能夠返回全部容許的方法,以便客戶端將其緩存。

Access-Control-Allow-Headers(當預請求中包含Access-Control-Request-Headers時必須包含) – 這是對預請求當中Access-Control-Request-Headers的回覆,和上面同樣是以逗號分隔的列表,能夠返回全部支持的頭部。

Access-Control-Allow-Credentials(可選) – 和簡單請求當中做用相同。

Access-Control-Max-Age(可選) – 以秒爲單位的緩存時間,容許時應當儘量緩存。

5.2.2.二、CORSFilter
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <filter>
        <filter-name>CorsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
        <init-param>
            <param-name>cors.allowed.origins</param-name>
            <param-value>http://127.0.0.1:8020</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowed.methods</param-name>
            <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowed.headers</param-name>
            <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
        </init-param>
        <init-param>
            <param-name>cors.exposed.headers</param-name>
            <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
        </init-param>
        <init-param>
            <param-name>cors.support.credentials</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.preflight.maxage</param-name>
            <param-value>10</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
web.xml
@WebServlet(name = "FilterCORSServlet", urlPatterns = "/filtercors")
public class FilterCORSServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet( request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("{\"name\":\"Book\"}");
    }
}
服務器
<script type="text/javascript" src="js/jquery-1.11.3.js" ></script>
        <script type="text/javascript">
            $.ajax({
                type:"post",
                url:"http://localhost:8080/filtercors",
                contentType:"application/json;charset=utf-8",
                dataType:"json",
                success:function(data){
                    $("body").text(data.name);
                }
            });
        </script>
客服端

結果:

5.2.2.二、Spring MVC4.2+CORS註解

方法1、若是想對一系列接口添加 CORS 配置,能夠在類上添加註解,對該類聲明全部接口都有效:

@Component
@RequestMapping("/cors")
@CrossOrigin(
        origins = {"http://127.0.0.1:8020"},
        allowedHeaders = "*",
        methods = {
                RequestMethod.GET,RequestMethod.POST,RequestMethod.OPTIONS
        },
        allowCredentials = "true",
        maxAge = 90
)
public class corsController {

    //跨域 CORS--複雜請求
    @RequestMapping(value = "/cors01")
    @ResponseBody
    public String cors01() {
        return "{\"name\":\"Tom\",\"age\":999}";
    }
}
控制器
<script type="text/javascript" src="js/jquery-1.11.3.js" ></script>
        <script type="text/javascript">
            $.ajax({
                type: "POST",
                url:"http://localhost:8080/cors/cors01",
                contentType:"application/json;charset=utf-8",
                dataType:"json",
                success:function(data){
                    $("body").text(data.name);
                }
            });
        </script>
客戶端

結果:

方法2、修改配置文件:

<!--跨域-->
    <mvc:cors>
        <mvc:mapping path="/cors/*"
                     allowed-origins="http://127.0.0.1:8020"
                     allowed-methods="POST,GET,OPTIONS,DELETE,PUT"
                     allowed-headers="Content-Type,ContentType,Access-Control-Allow-Headers, Authorization, X-Requested-With"
                     allow-credentials="true"/>
    </mvc:cors>
mvcXML
@Component
@RequestMapping("/cors")
public class corsController {

    //跨域 CORS--複雜請求
    @RequestMapping(value = "/cors01")
    @ResponseBody
    public String cors01() {
        return "{\"name\":\"Tom\",\"age\":999}";
    }
}
控制器
<body>
        <script type="text/javascript" src="js/jquery-1.11.3.js" ></script>
        <script type="text/javascript">
            $.ajax({
                type: "POST",
                url:"http://localhost:8080/cors/cors01",
                contentType:"application/json;charset=utf-8",
                dataType:"json",
                success:function(data){
                    $("body").text(data.name);
                }
            });
        </script>
    </body>
客戶端
相關文章
相關標籤/搜索