产生原因
浏览器同源策略安全限制(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;
}
}