天天看點

前後端分離項目經典跨域通路問題:四種常用方法。解決Allow-Origin header is present on the requested resource1.什麼是跨域?2.同源政策3.項目場景*4.解決方法(重點)

目錄導航

  • 1.什麼是跨域?
  • 2.同源政策
  • 3.項目場景
  • *4.解決方法(重點)
    • (1)使用@CrossOrigin注解
    • (2)使用corsfilter過濾器
    • (3)全局跨域設定。(推薦)
        • 繼承WebMvcConfigurer,通過addCorsMappings方法實作跨域通路。
    • **(4)nginx反向代理(代理轉發)重要

1.什麼是跨域?

(1)簡單的來說,跨域就是浏覽器核心同源政策對JavaScript代碼的一種限制。例如在目前伺服器的網站下不可執行另外網站的js代碼。

(2)常見的例如:dom和js對象無法擷取,ajax請求伺服器資料顯示:No ‘Access-Control-Allow-Origin’ header is present on the requested resource.錯誤。

2.同源政策

(1)同源政策是浏覽器的行為,是為了保護本地資料不被JavaScript代碼擷取回來的資料污染,是以攔截的是用戶端發出的請求回來的資料接收,即請求發送了,伺服器響應了,但是無法被浏覽器接收。

(2)浏覽器判斷同源的标準:

首先分析一下一個url的組成:http://localhost:8080/xxx.html

協定:http https 都是常見的協定

ip:一般本機的ip都是127.0.0.1或localhost來代替。

端口:比如常見的網站端口預設是80,等等。

http://localhost/bbb.html 與 http://localhost/aaa.html 同源 協定 ip 端口都一緻

http://localhost/bbb.html 與 https://localhost/aaa.html 跨域 協定不一緻

http://localhost/bbb.html 與 http://127.0.0.1/aaa.html 跨域 ip 不一緻(浏覽器認為localhost和127.0.0.1是屬于跨域,很多人會混淆)

http://localhost/xxx.html 與 http://localhost:8080/xxx.html 端口不一緻 屬于跨域

3.項目場景

(1)前端項目釋出服務端口為80,後端服務端口為8081的情況下。這時候前端ajax請求後端服務就屬于跨域通路,傳回的資料将會被浏覽器攔截,進而報錯。(Allow-Origin’ header is present on the requested resource)

*4.解決方法(重點)

(1)使用@CrossOrigin注解

前後端分離項目經典跨域通路問題:四種常用方法。解決Allow-Origin header is present on the requested resource1.什麼是跨域?2.同源政策3.項目場景*4.解決方法(重點)
前後端分離項目經典跨域通路問題:四種常用方法。解決Allow-Origin header is present on the requested resource1.什麼是跨域?2.同源政策3.項目場景*4.解決方法(重點)

(2)使用corsfilter過濾器

前後端分離項目經典跨域通路問題:四種常用方法。解決Allow-Origin header is present on the requested resource1.什麼是跨域?2.同源政策3.項目場景*4.解決方法(重點)

整理好的代碼片段如下:

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;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        //是否允許請求帶有驗證資訊
        corsConfiguration.setAllowCredentials(true);
		corsConfiguration.addAllowedOriginPattern("http://localhost:8081");  //單個域名設定
        /*允許服務端通路的用戶端請求頭*/
        corsConfiguration.addAllowedHeader("*");
        /*允許通路的方法名,GET POST等*/
        corsConfiguration.addAllowedMethod("*");
        //注冊url路徑,/**為全部路徑比對
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}
           

(3)全局跨域設定。(推薦)

繼承WebMvcConfigurer,通過addCorsMappings方法實作跨域通路。

代碼如下:

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("/**").allowedOriginPatterns("*")
        		//注冊可以請求的方法
                .allowedMethods("GET", "HEAD", "POST","PUT", "DELETE", "OPTIONS")
                .allowCredentials(true).maxAge(3600);
    }
}
           

**(4)nginx反向代理(代理轉發)重要

先上配置,如下:配置檔案在安裝好的nginx路徑下的conf檔案夾中的nginx.conf檔案

events {
		worker_connections  1024;
	}
http{
	
	server {
			   listen 8081;
			   server_name 192.168.1.100;

			   location / {
			   		proxy_set_header Host $http_host;
					proxy_set_header X-Real-IP $remote_addr;
					proxy_set_header REMOTE-HOST $remote_addr;
					proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
					proxy_pass http://192.168.1.100:8082;
			   if ($request_method = 'OPTIONS') {
						add_header Access-Control-Allow-Origin $http_origin;	
						add_header Access-Control-Allow-Credentials true;
						add_header Access-Control-Allow-Methods $http_access_control_request_method;
						add_header Access-Control-Allow-Headers $http_access_control_request_headers;
						add_header Access-Control-Max-Age 1728000;
						add_header Content-Length 300;
						return 204;
					}
				}
			}	
}
           
  1. 首先,配置檔案一定要有events{}和http{server{}}。
  2. 其次,server{}中的listen則是代表我們監聽的服務端口。(這裡是監聽192.168.1.100:8081的服務,然後轉發到8082端口)。
  3. server_name則是伺服器的ip或域名。
  4. 最最最重要的就是location的配置,’/'代表比對所有192.168.1.100:8081發出的請求。例如:http:192.168.1.100:8081/xx/xxx.js就會被/比對。
  5. proxy_set_header:設定轉發後的請求頭的相關資訊
  6. X-Real-IP :設定真實請求的ip
  7. REMOTE-HOST:設定真實的請求的真實主機位址
  8. X-Forwarded-For:第一個ip為用戶端請求的ip,第二個則是代理ip(用戶端:http://localhost:8081,代理:http://localhost:8082)
  9. proxy_pass:代理轉發url。就是由nginx發送http://localhost:8082,這樣nginx和背景就處于同源下,這樣就實作跨域通路了。
  10. 注意: 當proxy_pass的url後面跟上/斜杆時,轉發的url有以下情況

    假設現在用http://localhost:8081/aaa/xxx.html去通路。

    ① 當location /aaa/ {

    proxy_pass http://localhost:8082

    } 代理url:http://localhost:8082/aaa/xxx.html

    ② 當location /aaa/ {

    proxy_pass http://localhost:8082/

    } 代理url:http://localhost:8082/xxx.html

    由①、②對比,可以知道,當轉發的url後面有斜杆時,就會将比對http://localhost:8081/aaa/變成http://localhost:8082/,如果沒有,則隻替換前面的協定+ip+端口。

    ③ 當location /aaa/ {

    proxy_pass http://localhost:8082/bbb/

    } 代理url:http://localhost:8082/bbb/xxx.html

    ④ 當location /aaa/ {

    proxy_pass http://localhost:8082/bbb

    } 代理url:http://localhost:8082/bbbxxx.html

    由③、④對比,相同的是,都改變了url,不同的是,有斜杆的③分多了一級,而④是直接拼接。

  11. add_header:添加響應頭資訊。(跨域通路,并不是請求不到資料,而是接收不到資料)。是以,我們可以在響應頭中添加對應origin值,add_header Access-Control-Allow-Origin $http_origin; 這樣浏覽器就不會攔截。其他資料類似corsfilter配置的資訊,允許cookies、請求方法類型之類的,可自行上網查找。
  12. $request_method = ‘OPTIONS’:浏覽器将cors請求(跨域請求)分為兩種。一是簡單請求。二是非簡單請求。隻要同時滿足以下兩大條件,就屬于簡單請求。

    (1) 請求方法是以下三種方法之一:HEAD、GET、POST

    (2)HTTP的頭資訊不超出以下幾種字段:Accept、Accept-Language、ContentLanguage、Last-Event-ID

    (3)Content-Type:隻限于三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

    凡是不同時滿足上面兩個條件,就屬于非簡單請求。

    簡單請求浏覽器會自動添加一些附加的頭資訊,而非簡單請求浏覽器會多出一次附加的請求(options)。options請求會在正式請求前發送,該請求測試接口是否通過,通過才會發送正式請求。你需要确認背景不會攔截該請求,否則你的正式請求将無法被發送。

跨域通路記錄。

繼續閱讀