接上篇《微服务实战spring cloud alibaba(九)为服务增加spring cloud gateway网关》。上一篇我们为项目增加了spring cloud gateway,同时我们也能通过gateway请求到后端的微服务。今天这篇我们讲解下为spring cloud gateway增加跨域的filter。
一、什么是跨域
先来了解下什么是跨域。我们知道现如今我们的项目几乎都是前后端分离的方式进行开发,那么在访问的时候就会造成不同源的问题,即前端一个访问主机ip+端口,后端是另外一个主机ip+端口。官方的解释是:出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
二、在java项目中什么地方可以解决跨域
在java项目中我们解决跨域的地方很多,例如
2.1、可以在nginx层配置跨域解决,伪代码如下:
location / { root html; index index.html index.htm; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS,PUT,DELETE,OPTION'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Accept,Referer,Accept-Encoding,Accept-Language,Access-Control-Request-Headers,Access-Control-Request-Method,Connection,Host,Origin,Sec-Fetch-Mode'; # 代理到ip地址端口 proxy_pass http://xxxx:xxx; }
2.2、可以在spring cloud gateway里面配置跨域。但是在spring cloud gateway里面配置跨域也有两种方式
2.2.1、在配置文件里面配置跨域,伪代码如下:
spring: cloud: # 跨域配置 gateway: globalcors: cors-configurations: '[/**]': # 匹配所有请求 allowedOrigins: "*" #跨域处理 允许所有的域 allowedMethods: # 支持的方法 - GET - POST - PUT - DELETE
2.2.2、另外一种就是编写跨域配置类,实现跨域可控。创建一个CorsConfig.java的类(这种方法是我们常用的方法)
package org.gateway.service.gateway; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.util.pattern.PathPatternParser; /** * 跨域允许 */ @Configuration public class CorsConfig { @Bean public CorsWebFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允许cookies跨域 config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin config.addAllowedHeader("*");// #允许访问的头信息,*表示全部 config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.addAllowedMethod("OPTIONS");// 允许提交请求的方法类型,*表示全部允许 config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource source = new org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource( new PathPatternParser()); source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); } }
2.3、第三种是在各个服务里面配置跨域,伪代码如下:(这是最不推荐的一种方式)
2.3.1、使用注解的方式,伪代码如下:
在各个controller层添加@CrossOrigin
2.3.2、通过Configuration的方式,伪代码如下:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * AJAX请求跨域 */ @Configuration public class CorsConfig extends WebMvcConfigurerAdapter { static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" }; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods(ORIGINS).maxAge(3600); }
2.3.3、通过filter的方式,伪代码如下:
@Component public class CORSFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse res = (HttpServletResponse) response; // 设置允许Cookie res.addHeader("Access-Control-Allow-Credentials", "true"); // 允许http://www.xxx.com域(自行设置,这里只做示例)发起跨域请求 res.addHeader("Access-Control-Allow-Origin", "*"); // 设置允许跨域请求的方法 res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); // 允许跨域请求包含content-type res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { response.getWriter().println("ok"); return; } chain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { } }
好了,这篇文章就介绍到这里,总结一下:
1、配置跨域一般有3种方式,nginx配置、spring cloud gateway配置,service单独配置,比较推荐的是nginx配置和spring cloud gateway配置,最不推荐的是service里面单独配置 2、如果我们在请求的时候,有在request header里面自定义某个key,那么一定要把这个key添加到Access-Control-Allow-Headers这里面,不然在访问的时候,前端还是会提示跨域。
还没有评论,来说两句吧...