互联网并发与安全系列教程(15) - 基于Zuul实现API网关

简介: 互联网并发与安全系列教程(15) - 基于Zuul实现API网关

基于Zuul(网上找不到音标,读“猪”第四音)实现API网关,需要按如下步骤实现:

  1. 搭建Eureka注册中心
  2. 创建Zuul网关项目
  3. 创建A项目服务
  4. 创建B项目服务

流程示意图如下:

启动项目需要按上面顺序执行,否则会报错,下面开始讲解代码。

1. 创建Eureka注册中心

1.创建eureka_server项目

2.添加Maven依赖:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.1.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>Finchley.M7</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencies>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  </dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
  <repository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/libs-milestone</url>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
</repositories>
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

3.application.yml 配置信息

server:
  port: 8100
eureka:
  instance:
    hostname: server1
  client:
    serviceUrl:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    register-with-eureka: false
    fetch-registry: false

4.启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
  public static void main(final String[] args) {
    SpringApplication.run(EurekaApplication.class, args);
  }
}

2. 创建Zuul网关

1.创建zuul-gateway maven项目

2.添加maven依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Finchley.RC1</spring-cloud.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.0.1</version>
        <executions>
          <execution>
            <id>copy-conf</id>
            <phase>package</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <encoding>UTF-8</encoding>
              <outputDirectory>${project.build.directory}/ext/conf</outputDirectory>
              <resources>
                <resource>
                  <directory>ext/conf</directory>
                  <includes>
                    <include>logback.xml</include>
                  </includes>
                  <filtering>true</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.7.5.201505241946</version>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>default-prepare-agent-integration</id>
            <goals>
              <goal>prepare-agent-integration</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>com.spotify</groupId>
        <artifactId>docker-maven-plugin</artifactId>
        <version>0.4.3</version>
        <configuration>
          <imageName>hy_uav_gateway</imageName>
          <dockerDirectory>src/main/docker</dockerDirectory>
          <resources>
            <resource>
              <targetPath>/</targetPath>
              <directory>${project.build.directory}</directory>
              <include>${project.build.finalName}.jar</include>
              <include>ext/conf/logback.xml</include>
            </resource>
          </resources>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <repositories>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

3.配置application 依赖信息

###注册 中心
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8100/eureka/
server:
  port: 80
###网关名称
spring:
  application:
    name: service-zuul
### 配置网关反向代理    
zuul:
  routes:
    api-a:
      path: /api-a/**
      serviceId: project_a
    api-b:
      path: /api-b/**
      serviceId: project_b

4.ZuulApplication启动运行,并把过滤器拦截注册到SpringBoot容器

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class AppZuul {
  // @EnableZuulProxy 开启Zuul网关代理
  // @EnableEurekaClient 注册到EurekaC
  public static void main(String[] args) {
    SpringApplication.run(AppZuul.class, args);
  }
  // 注册到SpringBoot 容器
  @Bean
  public TokenFilter accessFilter() {
    return new TokenFilter();
  }
}

5.过滤器拦截参数

// 使用网关拦截Token参数
public class TokenFilter extends ZuulFilter {
  public Object run() throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    Object accessToken = request.getParameter("accessToken");
    if (accessToken == null) {
      // 返回错误信息
      ctx.setSendZuulResponse(false);
      ctx.setResponseStatusCode(401);
      ctx.setResponseBody("accessToken is null");
      return null;
    }
    return null;
  }
  public boolean shouldFilter() {
    return true;// 是否执行该过滤器,此处为true,说明需要过滤
  }
  @Override
  public int filterOrder() {
    return 0;// 优先级为0,数字越大,优先级越低
  }
  @Override
  public String filterType() {
    return "pre"; // 前置过滤器
  }
}

3. 创建A项目及B项目

A服务与B服务的创建方式大同小异,以A项目为例子:

1.创建api-a项目

2.添加maven依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Finchley.RC1</spring-cloud.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.0.1</version>
        <executions>
          <execution>
            <id>copy-conf</id>
            <phase>package</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <encoding>UTF-8</encoding>
              <outputDirectory>${project.build.directory}/ext/conf</outputDirectory>
              <resources>
                <resource>
                  <directory>ext/conf</directory>
                  <includes>
                    <include>logback.xml</include>
                  </includes>
                  <filtering>true</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.7.5.201505241946</version>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>default-prepare-agent-integration</id>
            <goals>
              <goal>prepare-agent-integration</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>com.spotify</groupId>
        <artifactId>docker-maven-plugin</artifactId>
        <version>0.4.3</version>
        <configuration>
          <imageName>hy_uav_gateway</imageName>
          <dockerDirectory>src/main/docker</dockerDirectory>
          <resources>
            <resource>
              <targetPath>/</targetPath>
              <directory>${project.build.directory}</directory>
              <include>${project.build.finalName}.jar</include>
              <include>ext/conf/logback.xml</include>
            </resource>
          </resources>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <repositories>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

3.配置application 依赖信息(b项目名字为:project_b)

server:
  port: 8001
###服务名称
spring:
    application:
        name: project_a
###注册中心地址
eureka:
  client:
    service-url:
           defaultZone: http://localhost:8100/eureka

4.启动类(b项目index方法返回“我是B项目”)

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class AIndexController {
  @RequestMapping("/")
  public String index() {
    return "我是A项目....";
  }
  public static void main(String[] args) {
    SpringApplication.run(AIndexController.class, args);
  }
}

4. 测试

4.1 运行Eureka注册中心

启动应用:http://localhost:8100/,可以看到Eureka注册中心管理平台。

4.2 运行Zuul网关

会发现Zuul网关注册上Eureka中心了

4.3 运行A项目和B项目

可以看到项目A和项目B都注册上Eureka中心了

4.4 访问测试

浏览器输入http://localhost/api-a,返回内容如下

可以看出tonken为null,要加token。

访问:http://localhost/api-a?token=123456

访问:http://localhost/api-b?token=123456

目录
相关文章
|
11天前
|
安全 Java API
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(上)
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)
33 0
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(上)
|
1月前
|
安全 算法 API
API接口安全
API接口安全
465 2
|
1月前
|
数据采集 监控 安全
各种业务场景调用API代理的API接口教程
API代理的API接口在各种业务场景中具有广泛的应用,本文将介绍哪些业务场景可以使用API代理的API接口,并提供详细的调用教程和代码演示,同时,我们还将讨论在不同场景下使用API代理的API接口所带来的好处。
|
3月前
|
运维 监控 安全
调用钉钉机器人API接口将堡垒机安全运维告警单发给运维人员
调用钉钉机器人API接口将堡垒机安全运维告警单发给运维人员
85 0
|
4月前
|
机器学习/深度学习 JSON JavaScript
图文讲解 Stable Diffusion API 调用教程
Stable Diffusion 是一个先进的深度学习模型,用于创造和修改图像。这个模型能够基于文本描述来生成图像,让机器理解和实现用户的创意。使用这项技术的关键在于掌握其 API,通过编程来操控图像生成的过程。
|
1天前
|
安全 Java Unix
如何开展API安全实现
【4月更文挑战第29天】安全编码培训、安全编码、静态检测。
|
11天前
|
安全 Java API
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(下)
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)
20 0
|
11天前
|
安全 Java API
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(中)
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)
27 0
|
1月前
|
安全 API 数据安全/隐私保护
email api接口配置教程步骤详解
Email API是用于程序化访问邮件服务的工具,让开发者能集成邮件功能到应用中。配置Email API包括选择供应商(如SendGrid、Mailgun、AokSend),注册获取API密钥,配置API参数,及测试邮件发送。使用Email API能提升邮件发送的可靠性和效率,便于邮件管理及营销活动。AokSend支持大量验证码发送,适合高效邮件运营。