接上篇《微服务实战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这里面,不然在访问的时候,前端还是会提示跨域。

还没有评论,来说两句吧...