目录

  • 前言
  • SpringCloud Gatewy网关
  • 一.网关功能和工作原理
  • 二.网关的类型
  • 三.搭建网关
  • 四.路由断言工厂(Route Predicate Factory)
  • 五.路由过滤器(属于GatewayFilter)
  • 六.DefaultFilter过滤器(属于GatewayFilter)
  • 七.全局过滤器(GlobalFilter)
  • 八.过滤器执行顺序
  • 九.Gateway解决跨域问题


前言

微服务分为多个服务,有很多服务是内部人员要用的,但是现在谁都可以访问到,那我们该怎么办呢?

Spring Cloud最新面试题Spring Cloud Nacos详解之注册中心Spring Cloud Nacos详解之配置中心Spring Cloud Nacos详解之集群配置Spring Cloud Eureka详解Spring Cloud Frign详解Spring Cloud Ribbon详解Spring Cloud Hystrix详解

SpringCloud Gatewy网关

一.网关功能和工作原理

java ip白名单校验 spring cloud gateway 白名单_spring cloud

二.网关的类型

  • Gateway
    响应式编程,具有更好的性能。
  • Zuul
    阻塞式编程。

三.搭建网关

1.创建一个新的服务

java ip白名单校验 spring cloud gateway 白名单_gateway_02


java ip白名单校验 spring cloud gateway 白名单_spring cloud_03


java ip白名单校验 spring cloud gateway 白名单_java_04

2.添加网关依赖和nacos服务发现依赖

<!--nacos服务注册发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        
        <!--网关gateway依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

3.编写yml配置文件

server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
       - id: order-service  # 订单服务
         uri: lb://orderservice
         predicates:
           - Path=/order/**

四.路由断言工厂(Route Predicate Factory)

官网示例

属性

描述

示例

After

是某个时间点之后的请求

-After=2023-01-01T17:42:47.789-07:00[America/Denver]

(必须在2023年1月1日17点42分47秒之后发的请求才能通过,根据美国丹佛[America/Denver]的时间算)

Before

是某个时间点之前的请求

-Before=2022-02-22T22:22:22.433+8:00[Asia/Shanghai]

(必须在2022年2月22日22时22分22秒之前发的请求才能通过,根据[Asia/Shanghai]上海时间算)

Between

是某两个时间点之前的请求

-Between=时间[时区],时间[时区]

Cookie

请求必须包含某些cookie

- Cookie=ikun, rap

Header

请求必须包含某些header

- Header=X-Request-Id,\d+

Host

请求必须是访问某个host(域名)

- Host=**.kunkun,**com.cn

Method

请求方式必须是指定方式

-Method=GETPOST

Path

请求路径必须符合指定规则

-path=user/**

Query

请求参数必须包含指定参数

Query=ikun

RemoteAddr

请求者的ip必须是指定范围

- RemoteAddr=192.168.1.1/24

Weight

权重处理

五.路由过滤器(属于GatewayFilter)

对进入网关的请求和微服务返回的响应做处理。比如:添加请求头。
官网示例

1.配置网关服务yml文件

路由过滤器:对当前路由生效。
server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
		  filters:
        	- AddRequestHeader=Ikun,ji ni tai mei!  # 添加请求头,针对某个服务生效。

2.在添加请求头的服务编写代码

在用户服务的controller里面写
	/**
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
                          @RequestHeader(value = "Ikun", required = false) String ikun) {
        System.out.println("Ikun最喜欢的歌是什么:" + ikun);
        return userService.queryById(id);
    }

然后访问 localhost:10086/user/1,控制台就会打印 ikun 的值。

java ip白名单校验 spring cloud gateway 白名单_spring cloud_05

六.DefaultFilter过滤器(属于GatewayFilter)

DefaultFilter:对所有路由都生效。
server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
	   default-filters:
        - AddRequestHeader=Ikun,ji ni tai mei!  #添加请求头,全局生效

七.全局过滤器(GlobalFilter)

对进入网关的请求和微服务返回的响应做处理。和GatewayFilter作用一样

因为GatewayFilter是基于配置实现,处理的逻辑是固定的,GlobalFilter基于代码逻辑实现,更加灵活一些,可以用于验证用户身份等功能。

1.实现GlobalFilter接口

验证身份信息,根据authorization的值是否是ikun
// @Order(-1) 注解方式实现,如果有多个过滤器,越小越早走。
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        // 2.获取参数中的 authorization 参数
        String auth = params.getFirst("authorization");
        // 3.判断参数值是否等于 ikun
        if ("ikun".equals(auth)) {
            // 4.是,放行
            return chain.filter(exchange);
        }
        // 5.否,拦截
        // 5.1.设置状态码,未登录
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 5.2.拦截请求
        return exchange.getResponse().setComplete();
    }

	/**
	* 代码方式实现,实现 Ordered 接口,多个过滤器,返回值越小,越早走。
	**/
    @Override
    public int getOrder() {
        return -1;
    }
}

2.验证身份

(1) 如果authorization 参数不等于ikun或没有都会报错。

java ip白名单校验 spring cloud gateway 白名单_gateway_06

(2) authorization 参数等于 ikun正常访问。

java ip白名单校验 spring cloud gateway 白名单_spring cloud_07

八.过滤器执行顺序

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤链(集合)中,排序后依次执行每个过滤器**(DefaultFilter -> 路由过滤器 -> GlobalFilter)**。

1.为什么不是同一个过滤器可以放在一个过滤链中呢?由下面可得这三个过滤器本质上都是GatewayFilter

DefaultFilter 和 路由过滤器的实现都是 AddRequestHeaderGatewayFilterFactory 类,最后会生成一个真正的过滤器(GatewayFilter)。

java ip白名单校验 spring cloud gateway 白名单_java_08

GlobalFilter的实现是通过 GatewayFilterAdapter 适配器类实现了GatewayFilter,然后就可以把GlobalFilter适配成GatewayFilter

java ip白名单校验 spring cloud gateway 白名单_java ip白名单校验_09

2.路由过滤器和DefaultFilter怎么设置@Order顺序呢?

由spring指定order,按声明顺序1开始递增。

java ip白名单校验 spring cloud gateway 白名单_java ip白名单校验_10

扩展:

  • org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。
  • org.springframework.cloud.gateway.handler.FilteringlWebHandler#handle()方法会加载全局过滤器与前面的过滤器合并后根据order排序,组织过滤器链。

九.Gateway解决跨域问题

跨域: 浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题。
解决: 采用CORS方案,网关处理跨域采用的同样是CORS方案。(简单来说就是浏览器询问服务端让不让这个请求跨域,如果让会返回结果)。

在yml文件配置以下内容
spring:
  cloud:
	gateway:
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题(浏览器去询问服务端的请求就是options)
        corsConfigurations:
          '[/**]':
            allowedOrigins:  # 允许哪些网站的跨域请求
              -"http://localhost:8888"
              -"http://www.ikun.com"
            allowedMethods: # 允许的跨域ajax的请求方式          
              -"GET"
			  -"POST"
		      -"DELETE"
			  -"PUT"
			  -"OPTIONS"
			allowedHeaders: "*" # 允许请求头跨域
			allowCredentials: true # 是否允许携带cookie
			maxAge: 360000 # 这次跨域检测的有效期