谷粒商城基础篇--47、商品服务-API-三级分类-网关统一配置跨域 整个跨域问题的解决方案经验分享

1、现在项目有三个工程

硅谷商城前端工程

硅谷商城前端对于的后端工程:renren-fast

以及网关gulimall-gateway

前端工程访问后端的renren-fast,需要经过网关gulimall-gateway进行路由转发

即将vue项目里的请求都给网关,网关经过url处理后,去nacos里找到管理后台的微服务,就可以找到对应的端口了,这样我们就无需管理端口,统一交给网关管理端口接口

在vue前端的工程里面进行下面的设置

// api接口请求地址
window.SITE_CONFIG['baseUrl'] = 'http://localhost:88/api';
// 意思是说本vue项目中要请求的资源url都发给88/api,那么我们就让网关端口为88,然后匹配到/api请求即可,
// 网关可以通过过滤器处理url后指定给某个微服务
// renren-fast服务已经注册到了nacos中

其中http://localhost:88是网关的地址,前端所以的url请求都带上/api这个后缀名称

 

 

通过网关过滤器把api改成renren-fast服务,所以让renren-fast注册到服务注册中心,这样请求88网关转发到8080fast,网关收到/api的请求之后,转发到renren-fast

所以renren-fast和网关都必须注册到同一个注册中心中,这里使用的是nacos注册中心

第二步、将fast注册到服务注册中心
第二步、将fast注册到服务注册中心,这样请求88网关转发到8080fast

在fast里加入注册中心的依赖

<!--SpringCloud-nacos 注册中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

        <!--SpringCloud-nacos 配置中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

在renren-fast项目中 src/main/resources/application.yml添加nacos配置

spring:
  application:
    name: renren-fast    # 意思是把renren-fast项目也注册到nacos中(后面不再强调了),这样网关才能转发给
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # nacos
        

然后在fast启动类上加上注解@EnableDiscoveryClient,重启

@EnableDiscoveryClient
@SpringBootApplication
public class RenrenApplication {

    public static void main(String[] args) {
        SpringApplication.run(RenrenApplication.class, args);
    }

}

然后在nacos的服务列表里看到了renren-fast

问题解决:

如果报错gson依赖,就导入google的gson依赖

如果一直获取不到nacos信息, 则在resources路径下创建一个 bootstrap.properties

spring.application.name=renren-fast
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

 

接下来也就是最为重要的一步:在网关中实现最重要的网关gulimall-gateway,网关路由转发的配置

第三步、配置**gateway(网关)**模块中的application.yml文件, 添加网关

        - id: admin_route
          uri: lb://renren-fast # 路由给renren-fast (lb)负载均衡
          predicates:  # 什么情况下路由给它
            - Path=/api/**  # 默认前端项目都带上api前缀,就是我们前面题的localhost:88/api
          filters:
            - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}  # 把/api/* 改变成 /renren-fast/*fast找

上面配置的意思就是将

lb代表负载均衡
修改过vue的api之后, 此时验证码请求的是 http://localhost:88/api/captcha.jpg?uuid=72b9da67-0130-4d1d-8dda-6bfe4b5f7935

也就是说, 他请求网关, 路由到了renren-fast , 然后去nacos里找fast.的IP为localhost:8080

最后拼接后的正确的路径是: localhost:8080/renren-fast/captcha.jpg,网关去路由转发访问localhost:8080/renren-fast/captcha.jpg

所以要利用网关带路径重写, 参考https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-rewritepath-gatewayfilter-factory
接下来我们再浏览器vue前端工程执行访问

 

 上面在浏览器输入本地vue前端工程的地址:localhost:8001/#/login,输入用户名和密码的时候,底层会使用http请求向后端发起用户名和密码教研的登录接口

该接口地址为:/localhost:88/api/sys/login

这个时候浏览器会报错,浏览器会包跨域安全的问题,当前用户在页面上面输入的地址是localhost:8001/#/login,然后用户要使用浏览器去访问/localhost:88/api/sys/login

浏览器会对二者的域名、端口、url进行对比,发现不一致就会报跨域问题

跨域概括
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

跨域: 指的是浏览器不能执行其他网站的脚本. 它是由浏览器的同源策略造成的, 是浏览器对js施加的安全措施. (ajax可以)
同源策略: 是指 协议、域名、端口 都要相同, 其中有一个不同都会产生跨域

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js 同一域名下 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js 同一域名下不同文件夹 允许
http://www.a.com:8000/a.js
http://www.a.com/b.js 同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js 同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js 域名和域名对应ip 不允许
http://www.a.com/a.js
http://script.a.com/b.js 主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js 不同域名 不允许

 

 

解决跨域问题的两种办法:

 

 第一种使用nginx组件,前端vue组件部署在nginx中,后端网关通过nginx进行转发,这样的话浏览器访问前端工程和,发起的login登录请求都在同一个nging域名下面就不会存在跨域的问题

第二种

方法二: 配置当次请求允许跨域
在响应头中添加:参考:https://blog.csdn.net/qq_38128179/article/details/84956552

Access-Control-Allow-Origin : 支持哪些来源的请求跨域
Access-Control-Allow-Method : 支持那些方法跨域
Access-Control-Allow-Credentials :跨域请求默认不包含cookie,设置为true可以包含cookie
Access-Control-Expose-Headers : 跨域请求暴露的字段
CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:
Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
Access-Control-Max-Age :表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将失效
在网关网关统一配置跨域,在网关gulimall-gateway中增加一个filter解决方法:在网关中定义“GulimallCorsConfiguration”类,该类用来做过滤,允许所有的请求跨域。

package com.hgw.gulimall.gateway.config;

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.cors.reactive.UrlBasedCorsConfigurationSource;

/**
 * Data time:2022/3/14 21:17
 * StudentID:2019112118
 * Author:hgw
 * Description: 配置跨域,该类用来做过滤,允许所有的请求跨域。
 */
@Configuration
public class GulimallCorsConfiguration {

    @Bean        // 添加过滤器
    public CorsWebFilter corsWebFilter() {
        // 基于url跨域,选择reactive包下的
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        // 配置跨域信息
        CorsConfiguration configuration = new CorsConfiguration();
        // 允许跨域的头 *:表示所有
        configuration.addAllowedHeader("*");
        // 允许跨域的请求方式
        configuration.addAllowedMethod("*");
        // 允许跨域的请求来源
        configuration.addAllowedOrigin("*");
        // 是否允许携带cookie跨域
        configuration.setAllowCredentials(true);

        // `/**` :任意url都要进行跨域配置
        source.registerCorsConfiguration("/**",configuration);
        return new CorsWebFilter(source);
    }
}

开发中推荐第二种,生产上面部署推进使用第一种

 

posted on 2022-07-12 17:46  luzhouxiaoshuai  阅读(621)  评论(0编辑  收藏  举报

导航