## 何为跨域 跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。 所谓同源是指,域名,协议,端口均相同,举个栗子: **http://www.123.com/index.html 调用 http://www.123.com/server.json (非跨域)** **http://www.123.com/index.html 调用 http://www.456.com/server.json  (主域名不同:123/456,跨域)** **http://abc.123.com/index.html 调用 http://def.123.com/server.json (子域名不同:abc/def,跨域)** **http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.json (端口不同:8080/8081,跨域)** **http://www.123.com/index.html 调用 https://www.123.com/server.json (协议不同:http/https,跨域)** 请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。 ## 如何解决 ### Gateway配置 gateway为API网关,所有请求的闸口,只需在gateway这一层设置允许跨域即可 ~~~ @Configuration public class RouterFunctionConfiguration { /** * 这里为支持的请求头,如果有自定义的header字段请自己添加 */ private static final String ALLOWED_HEADERS = "blade-auth, Content-Type, Authorization"; private static final String ALLOWED_METHODS = "*"; private static final String ALLOWED_ORIGIN = "*"; private static final String ALLOWED_EXPOSE = "*"; private static final String MAX_AGE = "18000L"; @Bean public WebFilter corsFilter() { return (ServerWebExchange ctx, WebFilterChain chain) -> { ServerHttpRequest request = ctx.getRequest(); if (CorsUtils.isCorsRequest(request)) { ServerHttpResponse response = ctx.getResponse(); HttpHeaders headers = response.getHeaders(); headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS); headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS); headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN); headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE); headers.add("Access-Control-Max-Age", MAX_AGE); headers.add("Access-Control-Allow-Credentials", "true"); if (request.getMethod() == HttpMethod.OPTIONS) { response.setStatusCode(HttpStatus.OK); return Mono.empty(); } } return chain.filter(ctx); }; } } ~~~ ### Nginx配置(推荐) 核心思想就是通过nginx或者其他反代工具,将本是跨域的接口地址代理到本地,再调用本地代理后的地址,即可解决跨域问题。 ~~~ server { listen 80; server_name blade; root /usr/share/nginx/blade; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } location /api{ proxy_pass http://demo.springblade.org/api/web; add_header Cache-Control no-store; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } ~~~ ### 总结 * 从gateway配置跨域固然方便,配置一次,其他所有请求都支持了,但是这样会或多或少影响系统的性能,深一层次想,这其实并不是服务端该做的事情 * Nginx配置反代的模式,虽然看上去麻烦,需要每个地方都配置跨域,但是由于nginx的高性能,将API反向代理后,并不会有明显的损耗,同时也变相降低了服务端的压力。所以推荐使用Nginx或其他反代工具来解决跨域问题。