解决跨域问题

什么是跨域

跨域:根据浏览器的同源策略,浏览器会判断请求的URL(协议 + ip或域名 + 端口号)与目标URL的来源是否相同,如果不同,就会造成跨域问题。

造成跨越的三种情况

  1. 域名不同
  2. 域名相同,端口号不同
  3. 二级域名不同

解决跨域的方式

1. Spring Boot 解决跨域

创建配置类 CorsFilter
@Configuration
public class CrossDomainConfig {

    /**
     * 配置Spring提供的跨域过滤器
     */
    @Bean
    public CorsFilter corsFilter() {
        /* 跨域配置 */
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin(CorsConfiguration.ALL);// 设置访问源地址
        configuration.addAllowedHeader(CorsConfiguration.ALL);// 设置访问源请求头
        configuration.addAllowedMethod(CorsConfiguration.ALL);// 设置访问源请求方法
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        // 为所有请求添加跨域配置
        source.registerCorsConfiguration("/**", configuration);
        return new CorsFilter(source);
    }
}

2. Spring Cloud - Gateway 解决跨域

方案一:配置 bootstrap.xml 文件

导入依赖

 <!-- spring-cloud-starter-gateway -->
 <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
  </dependency>
  <!-- spring-cloud-starter-loadbalancer(与gateway一起使用,实现负载均衡) -->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  </dependency>

  <!-- Nacos 注册与发现中心 spring-cloud-starter-alibaba-nacos-discovery -->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  </dependency>

  <!-- Nacos 配置中心 spring-cloud-starter-alibaba-nacos-config -->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  </dependency>
  <!-- spring-cloud-starter-bootstrap(与配置中心一起使用) -->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
  </dependency>

浏览器在进行跨域请求时可能会先发一个 OPTIONS 请求以验证是否允许跨域,所以配置 add-to-simple-url-handler-mapping: true

server:
  port: 8899

spring:
  application:
    name: gateway-service
  profiles:
    active: dev
  cloud:
    nacos:
      # discovery 和 config 的 server-addr 同时需要的话,可以同时配置一个
      server-addr: localhost:8848
      discovery:
        namespace: gateway
      config:
        namespace: ${spring.cloud.nacos.discovery.namespace}
        file-extension: yml
    gateway:
      globalcors: # 全局的跨域处理
      	add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        cors-configurations: # 跨域配置列表
          '[/**]': # 匹配所有路径
            allowedOrigins: "*" # 允许哪些网站的跨域请求
            allowedMethods: # 允许跨域的请求方式
              - GET
              - POST
              - PUT
              - DELETE
              - OPTIONS
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 3600 # 这次跨域检测的有效期,OPTIONS 有效时长,前提:两次请求相同;如果在有效时长内,之后的OPTIONS 预检请求不会发送
方案二:创建全局过滤器
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
 
@Configuration
public class CorsFilter {
 
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter corsFilter() {
        return (exchange, chain) -> {
            ServerWebExchange.Builder webExchangeBuilder = exchange.mutate();
            webExchangeBuilder
                    .request(exchange.getRequest())
                    .response(exchange.getResponse());
 
            webExchangeBuilder
                    .response(exchange.getResponse()
                            .mutate()
                            .header("Access-Control-Allow-Origin", "*")
                            .header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS")
                            .header("Access-Control-Allow-Headers", "Content-Type")
                            .build());
 
            return chain.filter(webExchangeBuilder.build());
        };
    }
}

3. Nginx解决跨域(解决Nginx到网关的跨域)

server {
        listen       8000;// 监听前端的端口号
        server_name  localhost;
        location  / {
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080';// 路由到网关
                add_header Access-Control-Allow-Headers '*';
                add_header Access-Control-Allow-Methods '*';
                add_header Access-Control-Allow-Credentials 'true';
                return 204;
            }
            if ($request_method != 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:7060' always;
                add_header Access-Control-Allow-Credentials 'true';
            }
            proxy_pass  http://localhost:59200; 
        }
    }

注意:为了方便,Access-Control-Allow-Origin设置成了*,在开发测试的时候可以这么设置,但如果是生产环境,建议不要设置成*,最好是允许哪些域名访问就设置哪些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值