最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

面試突擊之跨域問題的解決方案詳解

 更新時間:2022年09月08日 08:34:19   作者:Java中文社群  
跨域問題本質是瀏覽器的一種保護機制,它的初衷是為了保證用戶的安全,防止惡意網(wǎng)站竊取數(shù)據(jù)。那怎么解決這個問題呢?接下來我們一起來看

跨域問題指的是不同站點之間,使用 ajax 無法相互調用的問題。跨域問題本質是瀏覽器的一種保護機制,它的初衷是為了保證用戶的安全,防止惡意網(wǎng)站竊取數(shù)據(jù)。 但這個保護機制也帶來了新的問題,它的問題是給不同站點之間的正常調用,也帶來的阻礙,那怎么解決這個問題呢?接下來我們一起來看。

1.跨域三種情況

在請求時,如果出現(xiàn)了以下情況中的任意一種,那么它就是跨域請求:

  • 協(xié)議不同,如 http 和 https;
  • 域名不同;
  • 端口不同。

也就是說,即使域名相同,如果一個使用的是 http,另一個使用的是 https,那么它們也屬于跨域訪問。常見的跨域問題如下圖所示:

2.跨域問題演示

接下來,我們使用兩個 Spring Boot 項目來演示跨域的問題,其中一個是端口號為 8080 的前端項目,另一個端口號為 9090 的后端接口項目。

2.1 前端網(wǎng)站

前端項目只需要在 resources 下放兩個文件,一個用于發(fā)送 ajax 請求的 jquery.js,另一個是 html 前端頁面,工程目錄如下圖所示:

其中前端頁面 index.html 的代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>跨域測試頁面</title>
    <script src="js/jquery.min.js"></script>
</head>
<body>
<h1>跨域測試</h1>
<div>
    <input type="button" onclick="mySubmit()" value=" 發(fā)送跨域請求 ">
</div>
<script>
    function mySubmit() {
        // 發(fā)送跨域請求
        jQuery.ajax({
            url: "http://localhost:9090/test",
            type: "POST",
            data: {"name": "Java"},
            success: function (result) {
                alert("返回數(shù)據(jù):" + result.data);
            }
        });
    }
</script>
</body>
</html>
復制代碼

2.2 后端接口

后端接口項目首先先在 application.properties 配置文件中,設置項目的端口號為 9090,如下所示:

server.port=9090

然后創(chuàng)建一個后端控制器,返回一個 JSON 格式的數(shù)據(jù),實現(xiàn)代碼如下:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;

@RestController
public class TestController {
    @RequestMapping("/test")
    public HashMap<String, Object> test() {
        return new HashMap<String, Object>() {{
            put("state", 200);
            put("data", "success");
            put("msg", "");
        }};
    }
}

以上兩個項目創(chuàng)建并啟動成功之后,使用前端項目訪問后端接口,因為端口不一樣,所以也屬于跨域訪問,運行結果如下圖所示:

3.解決跨域問題

在 Spring Boot 中跨域問題有很多種解決方案,比如以下 5 個:

  • 使用 @CrossOrigin 注解實現(xiàn)跨域;
  • 通過配置文件實現(xiàn)跨域;
  • 通過 CorsFilter 對象實現(xiàn)跨域;
  • 通過 Response 對象實現(xiàn)跨域;
  • 通過實現(xiàn) ResponseBodyAdvice 實現(xiàn)跨域。

當然如果你愿意的話,還可以使用過濾器來實現(xiàn)跨域,但它的實現(xiàn)和第 5 種實現(xiàn)類似,所以本文就不贅述了。

3.1 通過注解跨域

使用 @CrossOrigin 注解可以輕松的實現(xiàn)跨域,此注解既可以修飾類,也可以修飾方法。當修飾類時,表示此類中的所有接口都可以跨域;當修飾方法時,表示此方法可以跨域,它的實現(xiàn)如下:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;

@RestController
@CrossOrigin(origins = "*")
public class TestController {
    @RequestMapping("/test")
    public HashMap<String, Object> test() {
        return new HashMap<String, Object>() {{
            put("state", 200);
            put("data", "success");
            put("msg", "");
        }};
    }
}

以上代碼的執(zhí)行結果如下圖所示:

從上圖中可以看出,前端項目訪問另一個后端項目成功了,也就說明它解決了跨域問題。 優(yōu)缺點分析 此方式雖然雖然實現(xiàn)(跨域)比較簡單,但細心的朋友也能發(fā)現(xiàn),使用此方式只能實現(xiàn)局部跨域,當一個項目中存在多個類的話,使用此方式就會比較麻煩(需要給所有類上都添加此注解)。

3.2 通過配置文件跨域

接下來我們通過設置配置文件的方式就可以實現(xiàn)全局跨域了,它的實現(xiàn)步驟如下:

  • 創(chuàng)建一個新配置文件;
  • 添加 @Configuration 注解,實現(xiàn) WebMvcConfigurer 接口;
  • 重寫 addCorsMappings 方法,設置允許跨域的代碼。

具體實現(xiàn)代碼如下:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration // 一定不要忽略此注解
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 所有接口
                .allowCredentials(true) // 是否發(fā)送 Cookie
                .allowedOriginPatterns("*") // 支持域
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) // 支持方法
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

3.3 通過 CorsFilter 跨域

此實現(xiàn)方式和上一種實現(xiàn)方式類似,它也可以實現(xiàn)全局跨域,它的具體實現(xiàn)代碼如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration // 一定不能忽略此注解
public class MyCorsFilter {
    @Bean
    public CorsFilter corsFilter() {
        // 1.創(chuàng)建 CORS 配置對象
        CorsConfiguration config = new CorsConfiguration();
        // 支持域
        config.addAllowedOriginPattern("*");
        // 是否發(fā)送 Cookie
        config.setAllowCredentials(true);
        // 支持請求方式
        config.addAllowedMethod("*");
        // 允許的原始請求頭部信息
        config.addAllowedHeader("*");
        // 暴露的頭部信息
        config.addExposedHeader("*");
        // 2.添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 3.返回 CorsFilter 對象
        return new CorsFilter(corsConfigurationSource);
    }
}

3.4 通過 Response 跨域

此方式是解決跨域問題最原始的方式,但它可以支持任意的 Spring Boot 版本(早期的 Spring Boot 版本也是支持的)。但此方式也是局部跨域,它應用的范圍最小,設置的是方法級別的跨域,它的具體實現(xiàn)代碼如下:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

@RestController
public class TestController {
    @RequestMapping("/test")
    public HashMap<String, Object> test(HttpServletResponse response) {
        // 設置跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        return new HashMap<String, Object>() {{
            put("state", 200);
            put("data", "success");
            put("msg", "");
        }};
    }
}

3.5 通過 ResponseBodyAdvice 跨域

通過重寫 ResponseBodyAdvice 接口中的 beforeBodyWrite(返回之前重寫)方法,我們可以對所有的接口進行跨域設置,它的具體實現(xiàn)代碼如下:

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    /**
     * 內容是否需要重寫(通過此方法可以選擇性部分控制器和方法進行重寫)
     * 返回 true 表示重寫
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
    /**
     * 方法返回之前調用此方法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        // 設置跨域
        response.getHeaders().set("Access-Control-Allow-Origin", "*");
        return body;
    }
}

此實現(xiàn)方式也是全局跨域,它對整個項目中的所有接口有效。

4.原理分析

為什么通過以上方法設置之后,就可以實現(xiàn)不同項目之間的正常交互呢? 這個問題的答案也很簡單,我們之前在說跨域時講到:“跨域問題本質是瀏覽器的行為,它的初衷是為了保證用戶的訪問安全,防止惡意網(wǎng)站竊取數(shù)據(jù)”,那想要解決跨域問題就變得很簡單了,只需要告訴瀏覽器這是一個安全的請求,“我是自己人”就行了,那怎么告訴瀏覽器這是一個正常的請求呢? 只需要在返回頭中設置“Access-Control-Allow-Origin”參數(shù)即可解決跨域問題,此參數(shù)就是用來表示允許跨域訪問的原始域名的,當設置為“*”時,表示允許所有站點跨域訪問,如下圖所示:

所以以上 5 種解決跨域問題的本質都是給響應頭中加了一個 Access-Control-Allow-Origin 的響應頭而已。

演示項目源碼

https://gitee.com/mydb/springboot-examples/tree/master/spring-boot-cross

總結

跨域問題的本質是瀏覽器為了保證用戶的一種安全攔截機制,想要解決跨域問題,只需要告訴瀏覽器“我是自己人,不要攔我”就行。它的常見實現(xiàn)方式有 5 種:通過注解實現(xiàn)局部跨域、通過配置文件實現(xiàn)全局跨域、通過 CorsFilter 對象實現(xiàn)全局跨域、通過 Response 對象實現(xiàn)局部跨域,通過 ResponseBodyAdvice 實現(xiàn)全局跨域。

到此這篇關于面試突擊之跨域問題的解決方案詳解的文章就介紹到這了,更多相關跨域問題內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java Scoket實現(xiàn)雙向通信代碼詳解

    Java Scoket實現(xiàn)雙向通信代碼詳解

    這篇文章主要介紹了Java Scoket實現(xiàn)雙向通信代碼詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • JDK8中新增的Optional工具類基本使用

    JDK8中新增的Optional工具類基本使用

    Optional不是對null關鍵字的一種替代,而是對于null判定提供了一種更加優(yōu)雅的實現(xiàn),接下來通過本文給大家分享JDK8中新增的Optional工具類基本使用,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • Spring Cloud負載均衡及遠程調用實現(xiàn)詳解

    Spring Cloud負載均衡及遠程調用實現(xiàn)詳解

    這篇文章主要介紹了Spring Cloud負載均衡及遠程調用實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • java8 集合求差集、并集、交集的實例

    java8 集合求差集、并集、交集的實例

    下面小編就為大家分享一篇java8 集合求差集、并集、交集的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • Intellij IDEA菜單欄不見了(Main Menu as Separate Toolbar)恢復菜單欄顯示的解決辦法

    Intellij IDEA菜單欄不見了(Main Menu as Separat

    有人問博主,關于Intellij IDEA菜單欄找不到了,被不小心的操作給隱藏了,怎么辦?下面給大家分享解決方案,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • AgileBoot?項目內統(tǒng)一的錯誤碼設計分析

    AgileBoot?項目內統(tǒng)一的錯誤碼設計分析

    這篇文章主要為大家介紹了AgileBoot?項目內統(tǒng)一的錯誤碼設計分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • 最新評論

    南昌市| 垫江县| 大荔县| 潢川县| 扬中市| 胶州市| 青岛市| 哈尔滨市| 延长县| 称多县| 大余县| 洮南市| 车险| 林芝县| 汶上县| 兰州市| 敦煌市| 凤山市| 林周县| 宁安市| 呼和浩特市| 双鸭山市| 武清区| 卓尼县| 普宁市| 饶平县| 九龙城区| 黄骅市| 东安县| 榆社县| 莲花县| 天等县| 穆棱市| 许昌市| 友谊县| 甘肃省| 宜兰县| 黎川县| 星子县| 广东省| 潜江市|