當前位置: 妍妍網 > 碼農

不要再問我跨域問題了,這篇文章全搞定

2024-06-04碼農

跨域問題產生、原理、解決方案

文章導讀

前言

跨域問題指的是在Web開發中,由於瀏覽器的 同源策略 限制,當一個網頁嘗試存取與它不同源( 協定、網域名稱或埠不同 )的資源時,可能會遇到安全限制導致無法正常存取的問題。這種策略旨在防止惡意網站讀取或修改其他網站的數據,保護使用者資訊保安。

這樣說可能有點抽象,下面具體展開說明。

跨域問題演示

通常情況下,我們主流的開發模式是:前後端分離。當我們從瀏覽器80存取伺服端81套用

下面我們用一個Web工程,一個後端工程具體簡單演示下。

1、Web工程結構:

  • application.properties

  • spring.application.name=springboot-cross-web
    server.port=8080

  • index.html 頁面

  • <!DOCTYPE html>
    <htmllang="en">
    <head>
    <metacharset="UTF-8">
    <metahttp-equiv="X-UA-Compatible"content="IE=edge">
    <metaname="viewport"content="width=device-width, initial-scale=1.0">
    <title>測試跨域請求頁面</title>
    <scriptsrc="js/jquery-3.5.1.min.js"></script>
    </head>
    <body>
    <div>
    <inputtype="button"onclick="crossSubmit()"value="跨域測試">
    </div>
    <script>
    functioncrossSubmit() {
    // 發送跨域請求
    jQuery.ajax({
    url"http://localhost:8081/api/cross",
    type"POST",
    data: {"key""Cross"},
    successfunction (result{
    alert("返回數據:" + result.data);
    }
    });
    }
    </script>
    </body>
    </html>

    2、後端工程結構:

  • application.properties

  • spring.application.name=springboot-cross
    server.port=8081

  • 測試套用


  • @RestController
    public classCrossAppController{
    @RequestMapping("/api/cross")
    public HashMap<String, Object> crossTest(){
    returnnew HashMap<String, Object>() {{
    put("state", 200);
    put("data", "success");
    }};
    }
    }

    3、啟動並測試

    瀏覽器報錯產生跨域問題。

    為什麽產生跨域問題?

    一般來講,通常產生跨域問題有以下幾種原因:

    1. 協定不同:如 https和http;

    2. 埠不同

    3. 網域名稱不同

    這就是常說的 同源策略 的問題。產生跨域問題的根源就是請求不同源。

    如何解決跨域問題?

    從上邊的問題來看,主要在於瀏覽器保護,對參數 "Access-Control-Allow-Origin" 的設定。

    主要有下解決方案:

    一、使用@CrossOrigin註解

    @RestController
    @CrossOrigin(origins = "*")
    public classCrossAppController{
    @RequestMapping("/api/cross")
    public HashMap<String, Object> crossTest(){
    returnnew HashMap<String, Object>() {{
    put("state", 200);
    put("data", "success");
    }};
    }
    }

    演示結果:

    二、使用全域跨域配置

    @Configuration
    public classWebConfigimplementsWebMvcConfigurer{
    @Override
    publicvoidaddCorsMappings(CorsRegistry registry){
    registry.addMapping("/api/cross")
    .allowedOrigins("*")
    .allowedMethods("GET""POST""PUT""DELETE")
    .allowedHeaders("*");
    //.allowCredentials(true);
    }
    }

    三、使用CorsFilter跨域

    @Component
    public classCorsFilterimplementsFilter{
    @Override
    publicvoiddoFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {
    HttpServletResponse response = (HttpServletResponse) res;
    HttpServletRequest request = (HttpServletRequest) req;
    // 設定允許的來源
    response.setHeader("Access-Control-Allow-Origin""*");
    // 處理預檢請求
    if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
    response.setStatus(HttpServletResponse.SC_OK);
    else {
    chain.doFilter(req, res);
    }
    }
    }

    四、使用Nginx來實作跨域

    server {
    listen 80;
    server_name your.domain.com;
    location / {
    # 添加CORS相關的響應頭
    add_header 'Access-Control-Allow-Origin''*';
    add_header 'Access-Control-Allow-Methods''GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers''DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    # 對於OPTIONS請求,直接返回204狀態碼
    if ($request_method = 'OPTIONS') {
    return 204;
    }
    # 其他配置...
    # 代理到後端服務或其他配置...
    # proxy_pass http://your_backend/;
    # 其他proxy_...指令...
    }
    }



    總結

  • 跨域問題指的是在Web開發中,由於瀏覽器的 同源策略 限制,導致無法正常存取的問題。

  • 主要原理就是請求參數 Access-Control-Allow-Origin



  • 👇🏻 點選下方閱讀原文,獲取魚皮往期編程幹貨。

    往期推薦