産生原因
浏覽器同源政策安全限制(cors詳情參考:跨域資源共享cors)
常見解決方案
1:本地開發環境
服務端
第一種:
//springboot1.5寫法
@Configuration
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
/**
* 允許請求跨域,上線時候拿掉
* 注意:
* 若允許用戶端發送cookie時,盡量精确指定請求源,不要使用*,使用*有時可以,有時還會跨域
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
//.allowedOrigins("*")
//允許請求的源,若允許用戶端發送cookie時,盡量精确指定請求源,不要使用*
.allowedOrigins("http://192.168.1.130:8081","http://localhost:8081")
//允許的請求方式
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
//允許用戶端發送cookie,預設為false,前端也要一緻的設定
.allowCredentials(true);
}
}
//springboot 2.0以上的方式
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
.allowedMethods("*")
.allowedOrigins("*")
.allowCredentials(true);
}
}
第二種(過濾器方式):
@Configuration
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
/**補充
* 攔截器的preHandle()方法的執行都在實際handler的方法(比如某個API對應的業務方法)之前
* 是以會導緻,部分請求在攔截器中校驗不通過,傳回false時,會跳過後續所有處理過程,無法到達addCorsMappings()方法的配置
* 是以還是會出現跨域問題
*
* 可以通過filter的方式解決
* 由于CorsFilter是定義在Web容器中的過濾器(實作了javax.servlet.Filter),
* 是以其執行順序先于Servlet,而SpringMVC的入口是DispatchServlet,是以該Filter會先于SpringMVC的所有攔截器執行。
* @return
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("http://192.168.1.130:8084");
config.setAllowCredentials(true);
config.addAllowedMethod("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
2:生産環境(通過代理伺服器)
跨域資源共享是由浏覽器的同源政策導緻的,伺服器之間的請求是不會有跨域産生的,可通過将請求交給代理伺服器轉發,即可解決
代理伺服器1(apache)
#核心配置參考(其中域名,ip等都已替換,别想着違法的事情了哈哈哈哈)
<VirtualHost *:80>
ServerAdmin [email protected]
ServerName www.ppf.com
#ProxyRequests On
DocumentRoot /var/www/html/test/ppf
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
#核心在這:在原本的請求路徑上多了一層 /api ,這樣浏覽器請求的接口的路徑就變成
# www.ppf.com/api/xxx,在浏覽器中還是在同一個源下(協定+域名+端口),自然就沒有跨源的問題了
ProxyPass /api http://53.87.109.86:8007/
ProxyPassReverse /api http://53.87.109.86:8007/
ProxyPass /psd http://127.0.0.1:8008/
ProxyPassReverse /psd http://127.0.0.1:8008/
</VirtualHost>
代理伺服器2(nginx)
server {
listen 80;
server_name www.ppf.com;
location / {
root /var/www/html/test/ppf;
index index.html index.htm;
}
#主接口
location /api {
proxy_pass http://127.0.0.1:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
#配置支援webSocket開始
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
#psd相關接口
location /psd {
proxy_pass http://127.0.0.1:8002/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
#配置支援webSocket開始
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}