SpringCloud系列:利用Zuul实现统一服务网关服务,简单实现IP白名单功能
2017-12-13 00:00
1401 查看
摘要: 本文基于SpringCloud Zuul实现统一网关服务、请求校验等功能,最后通过zuul过滤器实现IP白名单功能
一、概述
上篇文章我们介绍了基于Eureka注册服务提供者和消费者,使用Feign、Ribbon、Hystrix实现服务间的调用、负载均衡及服务熔断和降级功能。本文将基于上述服务,利用SpringCloud Zull实现对外的统一网关服务,可在网关服务内实现签名验证、IP过滤、统一转发等功能,同时基于Hystrix实现对服务的监控功能
二、功能开发实现
1.创建统一网关服务
创建普通的SpringBoot项目gateway,在pom.xml文件中增加如下依赖
在GatewayApplication主方法上添加@EnableZuulProxy注解,启用服务路由功能。查看@EnableZuulProxy源码可知,其包含了服务注册和断路保护注解功能
2.服务路由配置
Spring Cloud Zuul通过与 Eureka的整合,实现了对服务实例的自动化维护,所以在使用服务路由配置的时候,我们不需要像传统路由配置方式那样为serviceId去指定具体的服务实例地址,只需要通过一组
修改配置文件,配置转发到eureka-consumer服务的请求路由
启动服务,所有向/eureka-consumer/**的请求都会被转发到服务名为eureka-consumer的服务上去,打开postman测试请求
从日志中可以看出,zuul从DynamicServerListLoadBalancer中根据Ribbon负载均衡算法从服务列表中选取后端服务,然后发送请求,返回结果。
对于面向服务的路由配置,除了使用path和serviceId映射的配置方式之外,还有一种更简洁的配置方式:
修改配置文件,重启服务,用postman调用服务,可得同样的路由规则
3.实现IP白名单功能
我们主要利用Zuul的过滤器来实现该功能,其过滤器还可以用来实现统一的签名和验签服务以及其他任何你需要的服务,本例实现简单的IP过滤功能
新建IPFilter类,继承ZuulFilter,实现其方法
重启服务,再次发送请求,本地IP被禁止访问
在上面实现的过滤器代码中,我们通过继承ZuulFilter类并重写了下面的四个方法来实现自定义的过滤器.
三、小结
Demo源码地址:https://gitee.com/gengkangkang/springcloud.git
一、概述
上篇文章我们介绍了基于Eureka注册服务提供者和消费者,使用Feign、Ribbon、Hystrix实现服务间的调用、负载均衡及服务熔断和降级功能。本文将基于上述服务,利用SpringCloud Zull实现对外的统一网关服务,可在网关服务内实现签名验证、IP过滤、统一转发等功能,同时基于Hystrix实现对服务的监控功能
二、功能开发实现
1.创建统一网关服务
创建普通的SpringBoot项目gateway,在pom.xml文件中增加如下依赖
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
在GatewayApplication主方法上添加@EnableZuulProxy注解,启用服务路由功能。查看@EnableZuulProxy源码可知,其包含了服务注册和断路保护注解功能
@EnableCircuitBreaker @EnableDiscoveryClient @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(ZuulProxyMarkerConfiguration.class) public @interface EnableZuulProxy { }
2.服务路由配置
Spring Cloud Zuul通过与 Eureka的整合,实现了对服务实例的自动化维护,所以在使用服务路由配置的时候,我们不需要像传统路由配置方式那样为serviceId去指定具体的服务实例地址,只需要通过一组
zuul.routes.<route>.path与
zuul.routes.<route>.serviceId参数对的方式配置即可。
修改配置文件,配置转发到eureka-consumer服务的请求路由
spring.application.name=gateway server.port=9103 #注册用IP地址代替服务名 eureka.instance.preferIpAddress=true eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${spring.application.name}:${server.port} eureka.client.serviceUrl.defaultZone=http://10.17.5.45:9911/eureka/,http://10.17.5.46:9912/eureka/ #zuul默认为所有服务开启默认的路由,为了服务安全,此处关闭 zuul.ignored-services=* #自定义服务路由 zuul.routes.eureka-consumer.path=/eureka-consumer/** zuul.routes.eureka-consumer.serviceId=eureka-consumer
启动服务,所有向/eureka-consumer/**的请求都会被转发到服务名为eureka-consumer的服务上去,打开postman测试请求
从日志中可以看出,zuul从DynamicServerListLoadBalancer中根据Ribbon负载均衡算法从服务列表中选取后端服务,然后发送请求,返回结果。
对于面向服务的路由配置,除了使用path和serviceId映射的配置方式之外,还有一种更简洁的配置方式:
zuul.routes.<serviceId>=<path>,其中
<serviceId>用来指定路由的具体服务名,
<path>用来配置匹配的请求表达式。比如上面的例子,它的路由规则等价于上面通过
path与
serviceId组合使用的配置方式。
zuul.routes.eureka-consumer=/eureka-consumer/**
修改配置文件,重启服务,用postman调用服务,可得同样的路由规则
3.实现IP白名单功能
我们主要利用Zuul的过滤器来实现该功能,其过滤器还可以用来实现统一的签名和验签服务以及其他任何你需要的服务,本例实现简单的IP过滤功能
新建IPFilter类,继承ZuulFilter,实现其方法
@Component public class IPFilter extends ZuulFilter { Logger logger= LoggerFactory.getLogger(getClass()); @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx= RequestContext.getCurrentContext(); HttpServletRequest req=ctx.getRequest(); String ipAddr=this.getIpAddr(req); logger.info("请求IP地址为:[{}]",ipAddr); //配置本地IP白名单,生产环境可放入数据库或者redis中 List<String> ips=new ArrayList<String>(); ips.add("172.0.0.1"); if(!ips.contains(ipAddr)){ logger.info("IP地址校验不通过!!!"); ctx.setResponseStatusCode(401); ctx.setSendZuulResponse(false); ctx.setResponseBody("IpAddr is forbidden!"); } logger.info("IP校验通过。"); return null; } /** * 获取Ip地址 * @param request * @return */ public String getIpAddr(HttpServletRequest request){ String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } }
重启服务,再次发送请求,本地IP被禁止访问
在上面实现的过滤器代码中,我们通过继承ZuulFilter类并重写了下面的四个方法来实现自定义的过滤器.
filterType:过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。这里定义为
pre,代表会在请求被路由之前执行。另外还有“route”、“post”、"error”等类型,具体解释如下
/** * to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering, * "route" for routing to an origin, "post" for post-routing filters, "error" for error handling. * We also support a "static" type for static responses see StaticResponseFilter. * Any filterType made be created or added and run by calling FilterProcessor.runFilters(type) * * @return A String representing that type */ abstract public String filterType();
filterOrder:过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。
shouldFilter:判断该过滤器是否需要被执行。这里我们直接返回true,因此该过滤器对所有请求都会生效,实际运用中我们可以利用该函数来指定过滤器的有效范围。
run:过滤器的具体逻辑。IP校验不通过时我们通过
ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由,然后通过
ctx.setResponseStatusCode(401)设置了其返回的错误码,通过
ctx.setResponseBody(body)返回body内容。
三、小结
Demo源码地址:https://gitee.com/gengkangkang/springcloud.git
相关文章推荐
- SpringCloud调研系列5.2:服务网关Zuul组合API之Filter研究
- spring cloud 使用Zuul 实现API网关服务问题
- SpringCloud系列八:Zuul 路由访问(Zuul 的基本使用、Zuul 路由功能、zuul 过滤访问、Zuul 服务降级)
- Spring Boot + Spring Cloud 实现权限管理系统 后端篇(二十一):服务网关(Zuul)
- SpringCloud的微服务网关:zuul(理论)
- SpringBoot中实现拦截器级别的URl访问过快拦截,并利用JPA实现IP黑名单的功能。
- Spring Cloud Zuul微服务网关的API限流
- 2 微服务实战系列 - SpringCloud服务网关
- Spring Cloud学习--服务网关(Zuul)
- 详解利用SpringCloud搭建一个最简单的微服务框架
- 利用Spring Cloud Zuul实现动态路由示例代码
- 利用第三方服务平台实现简单的短信验证功能
- SpringCloud API网关服务(Spring Cloud Zuul)
- Spring Cloud Zuul--服务网关
- 利用SpringCloud搭建一个最简单的微服务框架
- API网关服务:Spring Cloud Zuul
- spring cloud 学习(6) - zuul 微服务网关
- SpringCloud(一):用springboot实现简单服务调用
- SpringCloud 笔记 (二)---- 简单搭建一个服务消费者,实现简单的ribbon负载均衡
- Spring Cloud Zuul--服务网关