zoukankan      html  css  js  c++  java
  • springCloud之路API路由网关Zuul

    1.简介

    简单的理解就是,相当于在所有服务的调用前加了一层防火墙,

    主要就是对外提供服务接口的时候,起到了请求的路由和过滤作用,也因此能够隐藏内部服务的接口细节,提高系统的安全性;

    官方文档:https://github.com/Netflix/zuul/wiki/How-We-Use-Zuul-At-Netflix

    2.简单实现

    构建项目模块:zuul-9001 , 其实相当于弄一个特殊的服务提供者

    pom.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>wfd360-station</artifactId>
            <groupId>com.wfd360.station</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>zuul-9001</artifactId>
        <dependencies>
            <dependency>
                <groupId>com.wfd360.station</groupId>
                <artifactId>common</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
            </dependency>
            <!--  eureka 依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <!-- actuator监控引入 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <!-- zuul路由网关 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zuul</artifactId>
            </dependency>
            <!-- 修改后立即生效,热部署 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>springloaded</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
        </dependencies>
    
    </project>
    View Code

    application.yml文件

    server:
      port: 9001
      context-path: /
    
    # 应用名称配置
    spring:
      application:
        name: service-zuul
    
    # eureka 注册中心配置
    eureka:
      instance:
        hostname: localhost #eureka客户端主机实例名称
        appname: service-zuul #客户端服务名称(可以随意取)
        instance-id: service-zuul:9001 #客户端实例名称(可以随意取)
        prefer-ip-address: true #显示ip地址
      client:
        service-url:
          #defaultZone: http://localhost:7001/eureka #eureka的服务器地址(单机)
          defaultZone: http://eureka7001.wfd360.com:7001/eureka/,http://eureka7002.wfd360.com:7002/eureka/,http://eureka7003.wfd360.com:7003/eureka/ # 集群
    
    # 服务提供者信息
    info:
      version: v2
      WeChat: 851298348
      负责人: 姿势帝
    View Code

    启动类代码:

    package com.wfd360;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    /**
     * Created by 姿势帝-博客园 on 2020/6/25.
     * 欢迎添加笔者wx(851298348)共同探讨、学习!
     */
    @SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
    @EnableZuulProxy
    public class ZuulApplication_9001 {
        /**
         * @param args
         */
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication_9001.class, args);
        }
    }
    View Code

    3.测试

    启动注册中心eureka 7001,启动服务提供者6004,启动zuul-9001

    点击: http://eureka7001.wfd360.com:7001/  查看注册中心中是否有zuul-9001的服务

    点击: http://localhost:6004/lock/ticket/11 测试服务提供是否正常

    通过网关访问服务规则:zuul网关ip+端口+服务提供者名称+服务提供者路由 ,案例如下

    点击:http://localhost:9001/service-lock/lock/ticket/10  看能否通过网关访问服务

     4.Zuul路由映射细节

    http://localhost:9001/service-lock/lock/ticket/10 这样直接通过服务名称service-lock相当于把服务名称直接暴露在外面,非常的不安全.....因此,外面需要做路由映射配置.

    4.1.路由映射配置

    # 服务名称映射
    zuul:
      routes:
        ticketServer.serviceId: service-lock
        ticketServer.path: /sl/**

    映射前的访问地址:http://localhost:9001/service-lock/lock/ticket/12

    映射后的访问地址:http://localhost:9001/sl/lock/ticket/12

     4.2.屏蔽根据服务名称访问的地址

    上一节中虽然我们可以通过映射后的地址访问,但是大家发现映射前的地址也可以访问,这样还是不安全;

    因此,我们需要屏蔽掉映射前的地址,也就是屏蔽根据服务名称访问的地址,如下:

    # 服务名称映射
    zuul:
      ignored-services: "service-lock" # 屏蔽根据服务名称访问的地址,如果写"*",表示屏蔽所有
      routes:
        ticketServer.serviceId: service-lock
        ticketServer.path: /sl/**

    映射前的访问地址:http://localhost:9001/service-lock/lock/ticket/12  ,你会发现现在这个地址不能访问了,因为已经屏蔽了.

    映射后的访问地址:http://localhost:9001/sl/lock/ticket/12 ,这个地址能正常访问.

    4.3.给路由加请求上下文,即请求前缀

    # 服务名称映射
    zuul:
      ignored-services: "service-lock" # 屏蔽根据服务名称访问的地址,如果写"*",表示屏蔽所有
      prefix: /wx_851298348 # 请求上下文,即请求前缀
      routes:
        ticketServer.serviceId: service-lock
        ticketServer.path: /sl/**

    加了前缀的请求地址为:http://localhost:9001/wx_851298348/sl/lock/ticket/12

    4.4.Zuul过滤器配置

    就相当于,我们传统项目的登录拦截器一样,过滤掉没有登录的用户,或黑名单ip,在微服务中我们一般是过滤掉不合法的token

    具体实现

    第一步:定义一个过滤器类

    package com.wfd360.filter;
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.apache.log4j.Logger;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * @author 姿势帝-博客园
     * @address https://www.cnblogs.com/newAndHui/
     * @WeChat 851298348
     * @create 07/22 10:29
     * @description
     */
    public class TokenFilter extends ZuulFilter {
        private static final Logger log = Logger.getLogger(TokenFilter.class);
    
        /**
         * 过滤器的类型
         * pre 表示请求前过滤
         *
         * @return
         */
        @Override
        public String filterType() {
            log.info("==========filterType=============");
            return "pre";
        }
    
        /**
         * 该过滤器执行顺序,越小越先执行,实际生产中可能有多个过滤器
         *
         * @return
         */
        @Override
        public int filterOrder() {
            log.info("==========filterOrder=============");
            return 0;
        }
    
        /**
         * 是否需要执行过滤器
         * return false 表示不执行
         * return true  表示需要执行
         *
         * @return
         */
        @Override
        public boolean shouldFilter() {
            log.info("==========shouldFilter=============");
            return true;
        }
    
        /**
         * 过滤器具体业务
         * <p>
         * 假设我们这里以token的长度必须大于5,否则是无效token
         * 当然实际生产中,我们的token一般是采用jwt机制实现的
         *
         * @return
         * @throws ZuulException
         */
        @Override
        public Object run() throws ZuulException {
            log.info("==========run=============");
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            String token = request.getParameter("token");
            log.info("请求路由:" + request.getRequestURL().toString());
            if (token == null || "".equals(token)) {
                log.error("token为空");
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(900);
                ctx.setResponseBody("{"message":"token is empty!"}");
                return null;
            }
            //  token判断逻辑
            if (token.length() <= 5) {
                log.error("token 非法");
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(900);
                ctx.setResponseBody("{"message":"token illegal!"}");
            }
            log.info("请求路由:" + request.getRequestURL().toString() + ",鉴权成功");
            return null;
        }
    }
    View Code

    第二步:添加到容器

    package com.wfd360.config;
    
    import com.wfd360.filter.TokenFilter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author 姿势帝-博客园
     * @address https://www.cnblogs.com/newAndHui/
     * @WeChat 851298348
     * @create 07/22 10:44
     * @description
     */
    @Configuration
    public class ZuulConfig {
        @Bean
        public TokenFilter tokenFilter() {
            return new TokenFilter();
        }
    }
    View Code

    第三步:测试

    访问:http://localhost:9001/wx_851298348/sl/lock/ticket/12?token=123456 ,成功,只要带有token,并且长度大于5都可以,其他的都会失败,大家自己进行演示!

     完美!

    springCloud课程与代码下载:https://www.cnblogs.com/newAndHui/p/13210228.html

  • 相关阅读:
    这个网站的设计太独特了
    mybatis—— 一个空格引发的血案
    Java IO--实现文件的加密解密
    Intellij IDEA如何生成JavaDoc--转载
    Java 在循环里发生异常会跳出循环
    idea格式化代码快捷键
    idea创建类时默认添加头部注释信息
    maven-helper解决依赖冲突
    Octotree插件
    idea .gitignore(git文件忽略)
  • 原文地址:https://www.cnblogs.com/newAndHui/p/13352871.html
Copyright © 2011-2022 走看看