项目介绍
- 前端项目 renren-fast-vue,baseurl 为
http://localhost:8080/renren-fast
,默认连接到后端项目 renren-fast - 后端项目 renren-fast,在端口
8080
启动 - 后端项目 mall-product,在端口
11000
启动
如果前端想请求后端项目 mall-product 提供的api,如何解决?
- 如想请求
http://localhost:11000/product/category/list/tree
- 需要修改前端 baseurl
http://localhost:8080/renren-fast
为http://localhost:11000
,这样的话,前端又会发生请求不到renren-fast
项目下的 api - 如果 mall-product 项目部署多份,分别在不同的端口启动,又怎么解决?
显然,前端请求的 baseurl 应该是一个公共路径。
那么,如何解决公共路径的问题呢?
此时,引入网关。让所有的请求,首先发送到网关,接着网关转发所有请求到相应的微服务即可。
网关微服务 mall-gateway
- 确保 renren-fast 和 mall-product 已经注册到注册中心 nacos 注册过程参考
- 创建 mall-gateway 微服务,并注册到注册中心,启动端口号
13000
- 修改 renren-fast-vue 前端项目的 baseurl 为
http://localhost:13000/api
- 解决路径问题
- 原来访问验证码的路径为:
http://localhost:8080/renren-fast/captcha.jpg?uuid=98fcaea6-71d5-43e4-8ce3-e839de8912bf
- 通过网关,访问 renren-fast 后端项目,验证码的请求路径为
http://localhost:13000/api/captcha.jpg?uuid=ee83f4f0-1bb8-4f0f-8f2e-d86d1ad305a7
,显然访问不到,因为renren-fast后端项目在8080
端口启动,并且路径为/renren-fast/captcha.jpg
而不是/api/captcha.jpg
- 在网关 mall-gateway 的 application.yml 增加如下配置,并重启网关微服务
注意:要保证路由成功,在高版本的spring cloud中,需要额外引入以下依赖:spring: application: name: mall-gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 gateway: routes: - id: admin_route uri: lb://renren-fast # 路由到 renren-fast 后端项目, renren-fast为注册到nacos的名字 predicates: - Path=/api/** # 如果请求路径是以api开头的任意路径,则通过 nacos 路由到 renren-fast后端服务 filters: - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment} # 路径重写,如/api/captcha.jpg 会被重写成 /renfen-fast/captcha.jpg
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency>
- 访问验证码成功:
- 原来访问验证码的路径为:
跨域问题
参考资料
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
http://www.ruanyifeng.com/blog/2016/04/cors.html
当输入用户名,密码的时候,发生跨域问题:
Access to XMLHttpRequest at 'http://localhost:13000/api/sys/login' from origin 'http://localhost:8001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
-
跨域
浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器对 javascript 施加的安全限制。
同源策略是指协议、域名、端口都要相同,其中一个不同都会产生跨域。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.121.74/b.js域名和域名对应ip 不允许 http://www.a.com/a.js
http://www.script.a.com/b.js主域相同,子域不同 不允许 http://www.a.com/a.js
http://a.com/b.js同一域名,不同二级域名 不允许,这种情况下也不允许访问cookie http://www.cnblogs.con/a.js
http://www.a.com/b.js不同域名 不允许 显然,从
http://localhost:8001
域名到http://localhost:13000/api/sys/login
域名跳转时,违反了浏览器的同源策略,因此产生跨域。 -
解决跨域问题,两种方法
方法一
: 利用nginx反向代理,解决跨域问题
所有的请求都通过nginx,让 nginx 来区别请求是发送到前端还是网关。发送到网关的请求,让网关转发到相应的微服务。方法二
:添加响应头
因为所有的请求都会经过 gateway 网关,在请求响应的过程中,经 gateway 网关给请求添加响应头,解决跨域问题。参数名 含义 Access-Control-Allow-origin 支持哪些来源的请求跨域 Access-Control-Allow-Methods 支持哪些方法跨域,如Get、Post、Put、Delete等 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 表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。
请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效 -
Spring Boot工程,mall-gateway 网关解决跨域【采用方法二】
@Configuration public class MallCorsConfiguration { @Bean public CorsWebFilter corsWebFilter() { UrlBasedCorsConfigurationSource ubcs = new UrlBasedCorsConfigurationSource(); // 对于任意路径(/**)都要配置跨域 CorsConfiguration corsConfiguration = new CorsConfiguration(); // 配置跨域 corsConfiguration.addAllowedHeader("*"); // Access-Control-Expose-Headers corsConfiguration.addAllowedMethod("*"); // Access-Control-Allow-Methods corsConfiguration.addAllowedOriginPattern("*"); // Access-Control-Allow-origin corsConfiguration.setAllowCredentials(true); // Access-Control-Allow-Credentials ubcs.registerCorsConfiguration("/**", corsConfiguration); return new CorsWebFilter(ubcs); } }
请求商品服务 mall-product
-
修改网关配置,因为之前配置的时候,默认所有请求 /api/** 都通过网关,发送到了后端服务 renren-fast。
spring: application: name: mall-gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 gateway: routes: - id: product_route uri: lb://mall-product predicates: - Path=/api/product/** # 这里路径/api/product/** 比 /api/** 路径更精确,所有放在上面。否则会先匹配模糊路由,到了renren-fast服务 filters: - RewritePath=/api/(?<segment>.*),/$\{segment} - id: admin_route uri: lb://renren-fast predicates: - Path=/api/** filters: - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}
-
测试经过网关,到达商品服务
总结
至此,renren-fast-vue 前端通过 mall-gate 网关,成功连接到后端 renren-fast 服务和 mall-product 服务。