AJAX跨域完全講解

来源:https://www.cnblogs.com/Java3y/archive/2018/03/01/8490439.html
-Advertisement-
Play Games

AJAX跨域完全講解 今天在慕課網上學習了AJAX跨域完全講解: "https://www.imooc.com/learn/947" 我在收集AJAX面試題的時候其實就已經有過AJAX跨域的問題的了,當時候知道了為什麼會存在跨域,以及跨域解決的方案有哪些,今天隨著課程的學習,又加深了AJAX跨域的理 ...


AJAX跨域完全講解

今天在慕課網上學習了AJAX跨域完全講解:https://www.imooc.com/learn/947

我在收集AJAX面試題的時候其實就已經有過AJAX跨域的問題的了,當時候知道了為什麼會存在跨域,以及跨域解決的方案有哪些,今天隨著課程的學習,又加深了AJAX跨域的理解,以此記錄下來。

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

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

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

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

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

解決跨域問題的思路

明顯地,跨域的問題是由於瀏覽器限制的,是XMLHttpRequest才會發生的,那麼我們可以以這個思路去找找解決思路:

對於瀏覽器的問題,可以使用相關的參數進行啟動瀏覽器,是可以解決跨域的問題,但是通用性是極低的,瞭解即可。

JSONP解決跨域

JSONP是JSON使用的一種補充方式,不是官方的協議。JSONP是一種解決跨域問題的一種協議

JSONP這種解決方案其實現在已經很少用了(複雜一點,需要修改後臺代碼),但我們可以適當瞭解一下。

使用步驟

在後端增加一個控制器,繼承AbstractJsonpResponseBodyAdvice類,完整代碼如下:


@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

    public JsonpAdvice() {
        // TODO Auto-generated constructor stub
        super("callback2");
    }
}

前端ajax請求:



// 伺服器返回的結果
    var result;

    $.ajax({
        url: base +"/get1",
        dataType: "jsonp",
        jsonp: "callback2",

        //是否需要緩存,如果這裡沒有配置緩存,那麼請求的URL還會有一個參數
        cache:true,
        success: function(json){
            result = json;
        }
    });

註意的是,前端AJAX的jsonp: "callback2",要和我們的Controllersuper("callback2");是一致的,不然是不會有效的。

JSONP原理是動態創建script來進行請求的:

JSONP的弊端:

  • 要對伺服器的代碼進行改動
  • 只支持GET方法(原理是動態創建script來進行請求的)
  • 發送的不是XMLHttpRequest請求(XMLHttpRequest請求有很多好用的特性)

參考資料:

CORS解決跨域問題

CORS解決跨域問題(也就是我們服務端被調用方解決跨域的思路)

對於CORS是怎麼理解的,我就直接摘抄一下:https://segmentfault.com/a/1190000012469713#articleHeader8的了。

在Java中,我們寫下麵這個過濾器,就可以完全解決跨域的問題了:



package com.imooc;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.buf.StringUtils;

public class CrosFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub

        HttpServletResponse res = (HttpServletResponse) response;
        
        HttpServletRequest req = (HttpServletRequest) request;
        
        
        //帶cookie的時候,origin必須是全匹配,不能使用*
        String origin = req.getHeader("Origin");
        if (!org.springframework.util.StringUtils.isEmpty(origin)) {
            res.addHeader("Access-Control-Allow-Origin", origin);
        }
        res.addHeader("Access-Control-Allow-Methods", "*");
        
        // 支持所有自定義頭和預檢命令(非簡單請求會有預檢命令)
        String headers = req.getHeader("Access-Control-Request-Headers");
        if (!org.springframework.util.StringUtils.isEmpty(headers)) {
            res.addHeader("Access-Control-Allow-Headers", headers);         
        }
        
        res.addHeader("Access-Control-Max-Age", "3600");
        // enable cookie
        res.addHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}

上面提到了非簡單請求,那什麼是非簡單請求呢,可以看下麵的圖:

非簡單請求會發出一個預檢命令的(當然了,我們上面的Filter已經解決預檢命令的問題了):

Spring框架解決

如果使用的是Spring框架的話,那就只需要一個註解就能夠解決跨域的問題了@CrossOrigin

HTTP伺服器層

我們在的商用開發中,一般請求的過程是這樣的:瀏覽器->HTTP伺服器(Nginx,Apache)->應用伺服器(Tomcat,Weblogic)

上面編寫的Filter、Spring框架都是在應用伺服器上解決的,我們也是可以通過HTTP伺服器(Nginx,Apache)來進行解決跨域問題的

Nginx我用過,Apache我倒是還沒用過,下麵就簡單記錄了Nginx和Apache是如何配置的:

Nginx配置:

Apache配置:

代理解決跨域問題

在之前的圖我們已經看到了,解決跨域的問題可以在“調用方”中來進行解決。

“調用方”解決跨域的問題是這個思路的:讓發送出去的請求代理成是本域的

舉個例子:

www.zhongfucheng.top是調用方

www.zhongfucheng.site是被調用方

它倆是不同域的,但我們可以在nginx或Apache上進行配置代理:將被調用方www.zhongfucheng.site映射成別的路徑

比如,像下麵的圖,將8080埠的映射成了ajaxServer,當調用方訪問ajaxServer路徑時,這樣的方法在外部看起來就不像是跨域了,像是訪問本地(8081埠),但實際訪問別的域(8080埠)

總結

令我感到最簡單的是通過Spring的註解就可以解決跨域的問題了,JSONP的方式已經是很少用的了,因為存在一定的弊端,但瞭解一下也無妨,畢竟可能面試的時候會問到。當沒有用任何框架的時候,寫Filter也不麻煩,也只是配置了一下HTTP頭信息而已。如果使用Nginx、Apache時,也可以用代理或者配置HTTP頭信息都可以解決。看完之後,有沒有覺得跨域問題就迎刃而解了。


如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章的同學,想要獲取更多的Java資源的同學,可以關註微信公眾號:Java3y


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、字元串 在Python中,加了引號的字元都被認為是字元串! 單引號、雙引號、多引號的區別? 單引號和 雙引號沒有任何區別,但是某種情況下需要單雙配合 如 msg = " My name is Small Nine ,I ' m 22 years old !’" 多引號的作用? 多引號的作用就是多 ...
  • 首先繼承Thread類,然後重寫Thread類的run()方法。 Thread類的子類的對象調用start()方法,然後虛擬機就會調用該線程的run()方法。 當程式執行到start()方法時,線程啟動,此時有兩條執行路徑,一條是主方法執行main方法,另一條是線程路徑執行線程run()里的代碼,兩 ...
  • 開散列法又叫鏈地址法(開鏈法)。 開散列法:首先對關鍵碼集合用散列函數計算散列地址,具有相同地址的關鍵碼歸於同一子集合,每一個子集合稱為一個桶,各個桶中的元素通過一個單鏈錶鏈接起來,各鏈表的頭結點存儲在哈希表中。 設元素的關鍵碼為37, 25, 14, 36, 49, 68, 57, 11, 散列表 ...
  • 解法: 最開始有三種思路: 最後採用了最後一種思路 github地址:https://github.com/CyanChan/Leetcode-Record ...
  • 近期項目中,用 jenkins 熱部署 web工程時,發現工程中靜態持有的線程(將ScheduledExecutorService定時任務存儲在靜態Map中),導致不定時出現資料庫訪問事務關閉異常,如下:org.springframework.transaction.CannotCreateTran ...
  • word裡面有2張表,需要找到第二張表,並寫入execl中: 代碼如下: 運行後生成文件 roro.xlsx,內容如下: ...
  • Java內部類 一、 含義 在Java編程語言里,程式是由類(class)構建而成的。在一個類的內部也可以聲明類,我們把這 樣的類叫做內部類。 二、 作用 實現了更好的封裝,我們知道,普通類(非內部類)的訪問修飾符不能為private或protected,而內部類可以。當我們將內部類聲明為priva ...
  • 之前寫了一篇ArrayList,那麼今天就寫一篇他的姊妹篇,LinkedList。 眾所周知,ArrayList底層數據是數組,可以在O(1)的時間內get到數據,但刪除和插入就要O(n)時間複雜度。 所以出現了鏈表,鏈表可以在O(1)的時間內插入,並且不會浪費記憶體,用多少就鏈接多少即可。 我們從以 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...