谷粒商城基础篇--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) 编辑 收藏 举报