中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ajax跨域產生的原因和解決方法

發布時間:2021-09-13 16:34:52 來源:億速云 閱讀:123 作者:chen 欄目:開發技術

本篇內容主要講解“ajax跨域產生的原因和解決方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“ajax跨域產生的原因和解決方法”吧!

AJAX跨域

課程介紹

  ●什么是AJAX跨域問題

  ●產生AJAX跨域問題的原因

  ●解決AJAX跨域問題的思路和方法

什么是AJAX跨域問題

  ●簡單來說,就是前端調用后端服務接口時

  ●如果服務接口不是同一個域,就會產生跨域問題

AJAX跨域場景

  ●前后端分離、服務化的開發模式

  ●前后端開發獨立,前端需要大量調用后端接口的場景

  ●只要后端接口不是同一個域,就會產生跨域問題

  ●跨域問題很普遍,解決跨域問題也很重要

AJAX跨域原因

  ●瀏覽器限制:瀏覽器安全校驗限制

  ●跨域(協議、域名、端口任何一個不一樣都會認為是跨域)

  ●XHR(XMLHttpRequest)請求

AJAX跨域問題解決思路

  ●瀏覽器:瀏覽器取下跨域校驗,實際價值不大

  ●XHR:不使用XHR,使用JSONP,有很多弊端,無法滿足現在的開發要求

  ●跨域:被調用方修改支持跨域調用(指定參數);調用方修改隱藏跨域(基于代理)

編寫測試代碼

  ●被調用方后端代碼編寫:Spring Boot

  ●調用方前端代碼編寫:Jquery

  ●引入前端Jasmine測試框架

為什么會發生產生跨域問題?

上面的圖也很清晰了,因為瀏覽器為了安全(同源),本身就限制了。

  ●當我們發送XMLHttpRequest請求的時候,如果請求的是別的域(主機域名、端口)不同時,那么就會產生跨域問題(客戶端無法獲取服務端返回的數據)

值得注意的是:跨域的問題是發生在XMLHttpRequest請求的,也就是說,不是XMLHttpRequest請求是不會有跨域問題的

  ●舉個很簡單的例子:在編寫網頁的時候,<img src = www.xxxx.xxxx/ >,URL不是本域的還是可以正常獲取該圖片的

解決跨域問題的思路

環境搭建

2-1 后端項目

代碼編寫

1.創建名為ajax-server的maven工程pom如下

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.myimooc</groupId>    <artifactId>ajax-server</artifactId>    <version>0.0.1-SNAPSHOT</version>    <packaging>jar</packaging>    <name>ajax-server</name>    <description>Demo project for Spring Boot</description>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.0.1.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>

2.編寫AjaxServerStart類

package com.myimooc.ajax.server;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * <br> * 標題: 啟動類<br> * 描述: AJAX跨域講解后端項目<br> * * @author zc * @date 2018/04/18 */@SpringBootApplicationpublic class AjaxServerStart {    public static void main(String[] args) {        SpringApplication.run(AjaxServerStart.class, args);    }}

3.編寫ResultBean類

package com.myimooc.ajax.server.vo;import java.io.Serializable;/** * <br> * 標題: REST請求響應POJO類<br> * 描述: 封裝請求響應結果<br> * * @author zc * @date 2018/04/18 */public class ResultBean implements Serializable{    private static final long serialVersionUID = 7867107433319736719L;    private String data;    public ResultBean(String data) {        this.data = data;    }    public String getData() {        return data;    }    public void setData(String data) {        this.data = data;    }}

4.編寫TestController類

package com.myimooc.ajax.server.controller;import com.myimooc.ajax.server.vo.ResultBean;import com.myimooc.ajax.server.vo.User;import org.springframework.web.bind.annotation.*;/** * <br> * 標題: 測試控制器<br> * 描述: 提供REST服務<br> * 使用 @CrossOrigin 注解支持跨域,可以放到類或方法上面 * @author zc * @date 2018/04/18 */@RestController@RequestMapping("/test")//@CrossOriginpublic class TestController {    @GetMapping("/get1")    public ResultBean get1() {        System.out.println("TestController.get1");        return new ResultBean("get1ok");    }    @PostMapping("/postJson")    public ResultBean postJson(@RequestBody User user) {        System.out.println("TestController.postJson");        return new ResultBean("postJson" + user.getName());    }    @GetMapping("/getCookie")    public ResultBean getCookie(@CookieValue(value = "cookie1") String cookie1) {        System.out.println("TestController.getCookie");        return new ResultBean("getCookie" + cookie1);    }    @GetMapping("/getHeader")    public ResultBean getHeader(            @RequestHeader("x-header1") String header1,            @RequestHeader("x-header2") String header2) {        System.out.println("TestController.getHeader");        return new ResultBean("getHeader" + header1+header2);    }}

2-2 前端項目

代碼編寫

1.創建名為ajax-client的maven工程pom如下

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.myimooc</groupId>    <artifactId>ajax-client</artifactId>    <version>0.0.1-SNAPSHOT</version>    <packaging>jar</packaging>    <name>ajax-client</name>    <description>Demo project for Spring Boot</description>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.0.1.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.webjars</groupId>            <artifactId>jquery</artifactId>            <version>3.3.0</version>        </dependency>        <dependency>            <groupId>org.webjars</groupId>            <artifactId>jasmine</artifactId>            <version>2.5.0</version>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>

2.編寫index.html

<!DOCTYPE html><html><head>    <meta charset="UTF-8">    <title>Index</title>    <link rel="stylesheet" type="text/css" href="/webjars/jasmine/2.5.0/jasmine.css">    <script src="/webjars/jquery/3.3.0/jquery.min.js"></script>    <script src="/webjars/jasmine/2.5.0/jasmine.js"></script>    <script src="/webjars/jasmine/2.5.0/jasmine-html.js"></script>    <script src="/webjars/jasmine/2.5.0/boot.js"></script></head><body><a href="#" onclick="get1()">發生get1請求</a><script>    function get1() {        $.getJSON("http://localhost:8080/test/get1").then(            function (res) {                console.log(res);            }        )    }    // 每一個測試用例的超時時間    jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;    // 請求的接口地址前綴    var base = "http://localhost:8080/test";    // 測試模塊    describe("AJAX講解", function () {        // 測試方法        it("get1請求", function (done) {            // 服務器返回的結果            var result;            $.getJSON(base + "/get1").then(                function (res) {                    result = res;                }            );            // 由于是異步請求,需要使用setTimeout來校驗            setTimeout(function () {                expect(result).toEqual({                    "data":"get1ok"                });                // 校驗完成,通知jasmine框架                done();            },100);        });        // // 測試方法        // it("jsonp請求", function (done) {        //     // 服務器返回的結果        //     var result;        //     $.ajax({        //         url: base + "/get1",        //         dataType: "jsonp",        //         jsonp:"callback2",        //         success: function (res) {        //             result = res;        //         }        //     });        //        //     // 由于是異步請求,需要使用setTimeout來校驗        //     setTimeout(function () {        //         expect(result).toEqual({        //             "data":"get1ok"        //         });        //        //         // 校驗完成,通知jasmine框架        //         done();        //     },100);        // });        // 測試方法        it("postJson請求", function (done) {            // 服務器返回的結果            var result;            $.ajax({                url:base+"/postJson",                type:"POST",                contentType:"application/json;charset=utf-8",                data:JSON.stringify({name:"testName"}),                success:function(res){                    result = res;                }            });            // 由于是異步請求,需要使用setTimeout來校驗            setTimeout(function () {                expect(result).toEqual({                    "data":"postJsontestName"                });                // 校驗完成,通知jasmine框架                done();            },100);        });        it("getCookie請求", function (done) {            // 服務器返回的結果            var result;            $.ajax({                url:base+"/getCookie",                xhrFields:{                    // 發送 AJAX 請求時帶上 cookie                    withCredentials:true                },                success:function(res){                    result = res;                }            });            // 由于是異步請求,需要使用setTimeout來校驗            setTimeout(function () {                expect(result).toEqual({                    "data":"getCookietestName"                });                // 校驗完成,通知jasmine框架                done();            },100);        });        it("getHeader請求", function (done) {            // 服務器返回的結果            var result;            $.ajax({                url:base+"/getHeader",                headers:{                    "x-header1":"AAA"                },                beforeSend:function(xhr){                   xhr.setRequestHeader("x-header2","BBB")                },                success:function(res){                    result = res;                }            });            // 由于是異步請求,需要使用setTimeout來校驗            setTimeout(function () {                expect(result).toEqual({                    "data":"getHeaderAAABBB"                });                // 校驗完成,通知jasmine框架                done();            },100);        });    });</script></body></html>

3.編寫application.properties

server.port=8081

4.編寫AjaxClientStart類

package com.myimooc.ajax.client;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class AjaxClientStart {    public static void main(String[] args) {        SpringApplication.run(AjaxClientStart.class, args);    }}

5.啟動AjaxServerStart和AjaxClientStart,并訪問http://localhost:8081,點擊發生get1請求,產生跨域問題如下

解決跨域

3-1 禁止檢查

Chrome瀏覽器的跨域設置

Windows方法

  參考文檔:https://www.cnblogs.com/laden...

  使用說明:在屬性頁面中的目標輸入框里加上:--disable-web-security --user-data-dir=C:MyChromeDevUserData

Mac OS方法

  參考文檔:http://blog.csdn.net/justinji...

  使用說明:用命令行打開 Google Chrome:open -a "Google Chrome" --args --disable-web-security

3-2 使用JSONP

代碼編寫

1.編寫JsonpAdvice類

package com.myimooc.ajax.server.controller;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;/** * <br> * 標題: JSONP 全局處理<br> * 描述: 統一處理JSONP<br> * * @author zc * @date 2018/04/18 */@ControllerAdvicepublic class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{    public JsonpAdvice() {        // 與前端約定好回調方法名稱,默認是callback        super("callback2");    }}

2.修改index.html

// 測試方法        it("jsonp請求", function (done) {            // 服務器返回的結果            var result;            $.ajax({                url: base + "/get1",                dataType: "jsonp",                jsonp:"callback2",                success: function (res) {                    result = res;                }            });            // 由于是異步請求,需要使用setTimeout來校驗            setTimeout(function () {                expect(result).toEqual({                    "data":"get1ok"                });                // 校驗完成,通知jasmine框架                done();            },100);        });

JSONP的弊端

服務器需要改動代碼支持只支持GET發送的不是XHR請求

3-3 支持跨域

常見的JavaEE架構

跨域解決方向

  ●被調用方解決

  ●基于支持跨域的解決思路

  ●基于Http協議關于跨域的相關規定,在響應頭里增加指定的字段告訴瀏覽器,允許調用

  ●跨域請求是直接從瀏覽器發送到被調用方

  ●修改被調用方的Http服務器

調用方解決

  ●基于隱藏跨域的解決思路

  ●跨域請求不會瀏覽器直接發送到被調用方

  ●而是從中間的Http服務器(Apache、Nginx)轉發過去

  ●修改調用方的Http服務器

被調用方支持跨域

  ●【重點】Web應用服務器(Tomcat、Netty、WebLogic或應用程序)實現

  ●Http服務器(Nginx)配置實現

  ●Http服務器(Apache)配置實現

使用Filter解決

編寫代碼

1.編寫CrosFilter類

package com.myimooc.ajax.server.config;import org.springframework.util.StringUtils;import javax.servlet.*;import javax.servlet.FilterConfig;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * <br> * 標題: 服務端解決跨域<br> * 描述: 使用Filter<br> * * @author zc * @date 2018/04/18 */public class CrosFilter implements Filter {    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    @Override    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {        HttpServletResponse res = (HttpServletResponse)response;        HttpServletRequest req = (HttpServletRequest)request;        // 支持所有域        String origin = req.getHeader("Origin");        if (!StringUtils.isEmpty(origin)){            // 支持任何域名的跨域調用 且 支持帶cookie(是被調用方域名的cookie,而不是調用方的cookie)            res.addHeader("Access-Control-Allow-Origin",origin);        }        // 指定允許的域,帶cookie時,origin必須是全匹配,不能使用 *//        res.addHeader("Access-Control-Allow-Origin","http://localhost:8081");        // 允許所有域,但不能滿足帶 cookie 的跨域請求//        res.addHeader("Access-Control-Allow-Origin","*");        // 支持所有自定義頭        String headers = req.getHeader("Access-Control-Allow-Headers");        if (!StringUtils.isEmpty(headers)){            // 允許所有header            res.addHeader("Access-Control-Allow-Headers",headers);        }        // 允許所有header//        res.addHeader("Access-Control-Allow-Headers","*");        // 指定允許的方法//        res.addHeader("Access-Control-Allow-Methods","GET");        // 允許所有方法        res.addHeader("Access-Control-Allow-Methods","*");        // 允許瀏覽器在一個小時內,緩存跨域訪問信息(即上面三個信息)        res.addHeader("Access-Control-Max-Age","3600");        // 啟用 cookie        res.addHeader("Access-Control-Allow-Credentials","true");        chain.doFilter(request,response);    }    @Override    public void destroy() {    }}

2.編寫FilterConfig類

package com.myimooc.ajax.server.config;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * <br> * 標題: 配置類<br> * 描述: 注冊CrosFilter<br> * * @author zc * @date 2018/04/18 */@Configurationpublic class FilterConfig {    @Bean    public FilterRegistrationBean registrationBean(){        FilterRegistrationBean filter = new FilterRegistrationBean();        filter.addUrlPatterns("/*");        filter.setFilter(new CrosFilter());        return filter;    }}

3.啟動AjaxServerStart和AjaxClientStart,并訪問http://localhost:8081,跨域解決

簡單請求與非簡單請求

  ●簡單請求:瀏覽器先發送真正的請求后檢查

  ●請求方法:GET、HEAD、POST的一種

  ●請求header:無自定義header;Content-Type為:text/plain、multipart/form-data、application/x-www-form-urlencoded的一種

  ●非簡單請求:瀏覽器先發預檢命令,檢查通過后,才發送真正的請求

  ●常見的有:PUT、DELETE

  ●其它條件:發送Json格式的請求、帶自定義header的請求

  ●預檢命令:瀏覽器檢測到跨域請求, 會自動發出一個OPTIONS請求, 就是所謂的預檢(preflight)請求。當預檢請求通過的時候,才發送真正的請求。

Nginx配置

  ●修改主機hosts文件增加映射本地域名:127.0.0.1 b.com(表示被調用方的域名)

  ●在conf目錄下創建vhost目錄

  ●修改nginx.conf在最后面增加一行代碼:include vhost/*.conf;

  ●在vhost目錄下創建b.com.conf

  ●啟動niginx,訪問b.com/test/get1

編寫b.com.conf

server{    listen 80;    server_name b.com;    location /{        proxy_pass http://localhost:8080/;        add_header Access-Control-Allow-Methods *;        add_header Access-Control-Max-Age 3600;        add_header Access-Control-Allow-Credentials true;        add_header Access-Control-Allow-Origin $http_origin;        add_header Access-Control-Allow-Headers $http_access_control_allow_headers;        if ($request_method = OPTIONS){            return 200;        }    }}

Apache配置

  ●修改conf/httpd.conf找到LoadModule vhost_alias_module module/mod_vhost_alias.so取消注釋

  ●修改conf/httpd.conf找到LoadModule proxy_module module/mod_ proxy.so取消注釋

  ●修改conf/httpd.conf找到LoadModule proxy_http_module module/mod_ proxy_http.so取消注釋

  ●修改conf/httpd.conf找到LoadModule headers_module module/mod_ headers.so取消注釋

  ●修改conf/httpd.conf找到LoadModule rewrite_module module/mod_ rewrite.so取消注釋

  ●修改conf/httpd.conf找到Include conf/extra/httpd-vhosts.conf取消注釋

  ●修改conf/extra/httpd-vhosts.conf在最后面增加下面的內容即可

<VirtualHost *:80>    ServerName b.com    ErrorLog "logs/b.com-error.log"    CustomLog "logs/b.com-access.log" common    ProxyPass / http://localhost:8080/    # 把請求頭的origin值返回到Access-Control-Allow-Origin字段    Header always set Access-Control-Allow-Origin "expr=%{req:origin}"    # 把請求頭的Access-Control-Allow-Headers值返回到Access-Control-Allow-Headers字段    Header always Access-Control-Allow-Headers "expr=%{Access-Control-Allow-Headers}"    Header always set Access-Control-Allow-Methods "*";    Header always set Access-Control-Max-Age "3600";    Header always set Access-Control-Allow-Credentials ""true";    # 處理預檢命令OPTIONS,直接返回204    RewriteEngine On    RewriteCond %{REQUEST_METHOD}OPTIONS    RewriteRule ^(.*)$"/" [R=204,L]</VirtualHost>

Spring框架支持

在類或方法上使用注解@CrossOrigin即可支持跨域

3-4 隱藏跨域

  ●使用Nginx反向代理實現

  ●修改主機hosts文件增加映射本地域名:127.0.0.1 a.com

  ●在vhost目錄下創建a.com.conf

  ●啟動niginx,訪問a.com/ajaxserver/get1

編寫a.com.conf

server{    listen 80;    server_name a.com;    location /{         proxy_pass http://localhost:8081/;    }    location /ajaxserver{         proxy_pass http://localhost:8080/test/;    }}

使用Apache反向代理實現

修改conf/extra/httpd-vhosts.conf在最后面增加下面的內容即可

<VirtualHost *:80>    ServerName a.com    ErrorLog "logs/a.com-error.log"    CustomLog "logs/a.com-access.log" common    ProxyPass / http://localhost:8081/    ProxyPass /ajaxserverapache http://localhost:8080/test</VirtualHost>

課程總結

4-1 課程總結

課程總結

  ●產生原因:主要是瀏覽器對Ajax請求的限制

  ●解決思路:JSONP、支持跨域、隱藏跨域

  ●核心原理:了解Http協議關于跨域方面的規定

  ●解決方法:使用Filter、Nginx正反向代理、Apache正反向代理、Spring框架支持

到此,相信大家對“ajax跨域產生的原因和解決方法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

蕉岭县| 二手房| 张家港市| 新蔡县| 平安县| 泰安市| 开封县| 富阳市| 永和县| 日喀则市| 峨眉山市| 大同县| 北海市| 江源县| 兴业县| 正镶白旗| 凤翔县| 竹山县| 仁怀市| 乳源| 大悟县| 贵州省| 凤山县| 淄博市| 武定县| 金堂县| 云南省| 榆树市| 元氏县| 攀枝花市| 宜丰县| 屏南县| 绩溪县| 东港市| 六盘水市| 云阳县| 大名县| 南岸区| 泽州县| 南江县| 鄂伦春自治旗|