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

解讀SpringBoot中addCorsMappings配置跨域與攔截器互斥問題的原因

 更新時間:2023年12月26日 16:49:18   作者:huangyaa729  
這篇文章主要介紹了解讀SpringBoot中addCorsMappings配置跨域與攔截器互斥問題的原因,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

SpringBoot中addCorsMappings配置跨域與攔截器互斥

如題,前兩天在做前后端分離項目時,碰到了這個問題,登錄token驗證的攔截器使項目中配置的跨域配置失效,導致瀏覽器拋出跨域請求錯誤,跨域配置如下:

public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                        registry.addMapping("/**")
                        .allowedOrigins(origins)
                        .allowedHeaders("*")
                        .allowCredentials(true)
                        .allowedMethods("*")
                        .maxAge(3600);
            }
        };
    }

通過在網(wǎng)上的查詢,發(fā)現(xiàn)了如下解釋

  • 但是使用此方法配置之后再使用自定義攔截器時跨域相關配置就會失效。
  • 原因是請求經(jīng)過的先后順序問題,當請求到來時會先進入攔截器中,而不是進入Mapping映射中,所以返回的頭信息中并沒有配置的跨域信息。瀏覽器就會報跨域異常。

然后參考了網(wǎng)上給出的方法,重新引入了跨域過濾器配置,解決了這個問題。

那最終這個問題產(chǎn)生的原因是什么的,真的如上訴所說嗎,我通過調試與研究源碼,找了原因。

在springMvc中,我們都知道路徑的映射匹配是通過DispatcherServlet這個類來實現(xiàn)的,最終的函數(shù)執(zhí)行在doDispatch()這個方法中:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request. 
		(1)mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
		(2)HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

		(3)if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
		(4)mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
		(5)mappedHandler.applyPostHandle(processedRequest, response, mv);
			}

在這個類中,我們關注(1)-(5)這幾句代碼,基本上整個映射執(zhí)行的邏輯就明了了:

  • (1)根據(jù)請求request獲取執(zhí)行器鏈(包括攔截器和最終執(zhí)行方法Handler)
  • (2)根據(jù)Handler獲取handlerAdapter;
  • (3)執(zhí)行執(zhí)行器鏈中的攔截方法(preHandle);
  • (4)執(zhí)行handler方法;
  • (5)執(zhí)行執(zhí)行器鏈中的攔截方法(postHandle);

在這個函數(shù)中我們并沒有看到什么時候執(zhí)行addCorsMappings這一配置內容,那它到底是什么時候添加的呢,那就需要仔細分析步驟(1)了:獲取整個執(zhí)行器鏈。

通過調試定位,我發(fā)現(xiàn)getHandle()最終執(zhí)行的AbstractHandlerMapping這個類的函數(shù)

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
(1)Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = getApplicationContext().getBean(handlerName);
		}

(2)HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		if (CorsUtils.isCorsRequest(request)) {
			CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
			CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
			CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
(3)	executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}
		return executionChain;
	}

這個函數(shù)中我也標記了(1)、(2)、(3)這三條語句:

  • (1)獲取request所需執(zhí)行的handler,具體邏輯不再細說,有興趣的可以參考我的另一篇文章
  • (2)獲取執(zhí)行器鏈,簡單來說就是把具體的執(zhí)行器和整個攔截器鏈組成一個鏈隊形,方便后續(xù)執(zhí)行;
  • (3)這個就是關鍵點,可能有的同學已經(jīng)看明白了,addCorsMapping配置就是在這塊引入的;

進入這個方法后,一切都明了了;

protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
			HandlerExecutionChain chain, CorsConfiguration config) {

		if (CorsUtils.isPreFlightRequest(request)) {
			HandlerInterceptor[] interceptors = chain.getInterceptors();
			chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
		}
		else {
			chain.addInterceptor(new CorsInterceptor(config));
		}
		return chain;
	}

先判斷request是否是預檢請求(不明白什么是預檢請求的可以自身搜索相關解釋,很多,不再贅述),是預檢請求則生成個預檢執(zhí)行器PreFlightHandler,然后在doDispatch函數(shù)(4)中執(zhí)行;

否則生成一個跨域攔截器加入攔截器鏈中,最終再doDispatch函數(shù)(3)處執(zhí)行,而因為攔截器是順序執(zhí)行的,如果前面執(zhí)行失敗異常返回后,后面的則不再執(zhí)行。

所以當跨越請求在攔截器那邊處理后就異常返回了,那么響應的response報文頭部關于跨域允許的信息就沒有被正確設置,導致瀏覽器認為服務不允許跨域,而造成錯誤;而當我們使用過濾器時,過濾器先于攔截器執(zhí)行,那么無論是否被攔截,始終有允許跨域的頭部信息,就不會出問題了。

另注:

對于預檢請求,一般token驗證時是不會攔截此請求的,因為預檢請求不會附帶任何參數(shù)信息,也就沒有所需的token信息,所以攔截時需過濾預檢請求

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Idea里github的圖形化操作配置方法

    Idea里github的圖形化操作配置方法

    這篇文章主要介紹了Idea里github的圖形化操作配置方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • SpringCloud之@FeignClient()注解的使用方式

    SpringCloud之@FeignClient()注解的使用方式

    這篇文章主要介紹了SpringCloud之@FeignClient()注解的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java web實現(xiàn)簡單留言板功能

    java web實現(xiàn)簡單留言板功能

    這篇文章主要為大家詳細介紹了java web實現(xiàn)簡單留言板功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • Java 鎖粗化與循環(huán)問題

    Java 鎖粗化與循環(huán)問題

    這篇文章主要介紹了Java 鎖粗化與循環(huán)的相關知識,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04
  • spring如何使用命名空間p簡化bean的配置

    spring如何使用命名空間p簡化bean的配置

    這篇文章主要介紹了spring如何使用命名空間p簡化bean的配置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01
  • SpringCloud Config配置加密解密用法解析

    SpringCloud Config配置加密解密用法解析

    這篇文章主要介紹了SpringCloud Config配置加密解密用法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Java實現(xiàn)操作excel表格

    Java實現(xiàn)操作excel表格

    在日常工作中,對Excel工作表格的操作處理可是多的數(shù)不清楚,下面是java語言對其的操作,有需要的小伙伴可以參考下
    2015-10-10
  • SpringBoot根據(jù)各地區(qū)時間設置接口有效時間的實現(xiàn)方式

    SpringBoot根據(jù)各地區(qū)時間設置接口有效時間的實現(xiàn)方式

    這篇文章給大家介紹了SpringBoot根據(jù)各地區(qū)時間設置接口有效時間的實現(xiàn)方式,文中通過代碼示例給大家講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • MyBatis利用攔截器實現(xiàn)數(shù)據(jù)脫敏詳解

    MyBatis利用攔截器實現(xiàn)數(shù)據(jù)脫敏詳解

    現(xiàn)代網(wǎng)絡環(huán)境中,敏感數(shù)據(jù)的處理是至關重要的,敏感數(shù)據(jù)包括個人身份信息、銀行賬號、手機號碼等,所以本文主要為大家詳細介紹了MyBatis如何利用攔截器實現(xiàn)數(shù)據(jù)脫敏,希望對大家有所幫助
    2023-11-11
  • Java實現(xiàn)人機對戰(zhàn)猜拳游戲

    Java實現(xiàn)人機對戰(zhàn)猜拳游戲

    這篇文章主要為大家詳細介紹了Java實現(xiàn)人機對戰(zhàn)猜拳游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07

最新評論

徐汇区| 北辰区| 无极县| 梧州市| 广灵县| 上杭县| 淅川县| 沙洋县| 秭归县| 华池县| 吴堡县| 花莲市| 广元市| 东兴市| 林甸县| 台北县| 东源县| 治县。| 莱州市| 额济纳旗| 连云港市| 霍林郭勒市| 北辰区| 四川省| 雷州市| 遂平县| 额济纳旗| 西安市| 绥化市| 宁武县| 华坪县| 临武县| 泊头市| 蒲城县| 平遥县| 扎赉特旗| 久治县| 开封市| 元阳县| 金平| 呼和浩特市|