互联网API开放平台安全设计(五)---APIGateway网关

什么是网关

随着互联网的快速发展,当前以步入移动互联、物联网时代。用户访问系统入口也变得多种方式,由原来单一的PC客户端,变化到PC客户端、各种浏览器、手机移动端及智能终端等。同时系统之间大部分都不是单独运行,经常会涉及与其他系统对接、共享数据的需求。所以系统需要升级框架满足日新月异需求变化,支持业务发展,并将框架升级为微服务架构。“API网关”核心组件是架构用于满足此些需求。

很多互联网平台已基于网关的设计思路,构建自身平台的API网关,国内主要有京东、携程、唯品会等,国外主要有Netflix、Amazon等。

网关框架框架

业界为了满足这些需求,已有相关的网关框架。

1、基于nginx平台实现的网关有:KONG、API Umbrella

2、自研发的网关有:apigee、Zuul

API网关设计

API网关是微服务架构(Microservices Architecture)标准化服务的模式。API网关定位为应用系统服务接口的网关,区别于网络技术的网关,但是原理则是一样。API网关统一服务入口,可方便实现对平台众多服务接口进行管控,对访问服务的身份认证、防报文重放与防数据篡改、功能调用的业务鉴权、响应数据的脱敏、流量与并发控制,甚至基于API调用的计量或者计费等等。组件设计如下:

网关的应用场景

  1. 黑白名单:实现通过IP地址控制禁止访问网关功能,此功能是应用层面控制实现,再往前也可以通过网络传输方面进行控制访问。
  2. 日志:实现访问日志的记录,可用于分析访问、处理性能指标,同时将分析结果支持其他模块功能应用。
  3. 协议适配:实现通信协议校验、适配转换的功能。
  4.  身份认证:负责网关访问身份认证验证,此模块与“访问认证中心”通信,实际认证业务逻辑交移“访问认证中心”处理。
  5. 计流限流:实现微服务访问流量计算,基于流量计算分析进行限流,可以定义多种限流规则。
  6. 路由:路由是API网关很核心的模块功能,此模块实现根据请求,锁定目标微服务并将请求进行转发。此模块需要与“服务发布管理中心”通信。“服务发布管理中心”实现微服务发布注册管理功能,与其通信获得目标微服务信息。

API网关部署

API网关是一个公共基础组件,无状态,可支持多套分布式部署。如下图所示:

互联网API开放平台安全设计(五)---APIGateway网关_第1张图片

互联网API开放平台安全设计(五)---APIGateway网关_第2张图片

基于Nginx实现API网关

Nginx配置

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {

        listen       80;

        server_name  localhost;

        location /api-a {

            proxy_pass   http://127.0.0.1:8000/;

            index  index.html index.htm;

        }

                   location /api-b {

            proxy_pass   http://127.0.0.1:8001/;

            index  index.html index.htm;

        }

    }

}

 

基于Zuul实现API网关

搭建注册中心

创建项目eureka_server

eureka_server pom依赖信息

<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">

      <modelVersion>4.0.0modelVersion>

      <groupId>com.itmayiedugroupId>

      <artifactId>eureka_serverartifactId>

      <version>0.0.1-SNAPSHOTversion>

      <parent>

           <groupId>org.springframework.bootgroupId>

           <artifactId>spring-boot-starter-parentartifactId>

           <version>2.0.1.RELEASEversion>

      parent>

 

     

      <dependencyManagement>

           <dependencies>

                 <dependency>

                      <groupId>org.springframework.cloudgroupId>

                      <artifactId>spring-cloud-dependenciesartifactId>

                      <version>Finchley.M7version>

                      <type>pomtype>

                      <scope>importscope>

                 dependency>

           dependencies>

      dependencyManagement>

      <dependencies>

 

           <dependency>

                 <groupId>org.springframework.cloudgroupId>

                 <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>

           dependency>

 

 

      dependencies>

 

     

      <repositories>

           <repository>

                 <id>spring-milestonesid>

                 <name>Spring Milestonesname>

                 <url>https://repo.spring.io/libs-milestoneurl>

                 <snapshots>

                      <enabled>falseenabled>

                 snapshots>

           repository>

      repositories>

 

      <build>

           <plugins>

                 <plugin>

                      <groupId>org.springframework.bootgroupId>

                      <artifactId>spring-boot-maven-pluginartifactId>

                 plugin>

           plugins>

      build>

project>

 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

server:

  port: 8100

eureka:

  instance:

    hostname: server1

  client:

    serviceUrl:

          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

    register-with-eureka: false

    fetch-registry: false

 启动类

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

 创建A服务项目

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class AIndexController {
	@RequestMapping("/")
	public String index() {
		return "我是A项目....";
	}

	public static void main(String[] args) {
		SpringApplication.run(AIndexController.class, args);
	}
}

 

server:

  port: 8000

spring:

    application:

        name: itmayiedu_a

eureka:

  client:

    service-url:

           defaultZone: http://localhost:8100/eureka

创建B服务项目

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class AIndexController {
	@RequestMapping("/")
	public String index() {
		return "我是B项目....";
	}

	public static void main(String[] args) {
		SpringApplication.run(AIndexController.class, args);
	}
}

 

server:

  port: 8000

spring:

    application:

        name: itmayiedu_a

eureka:

  client:

    service-url:

           defaultZone: http://localhost:8100/eureka

创建 zuul-gateway 项目

创建 zuul-gateway Pom依赖

 

      <parent>

           <groupId>org.springframework.bootgroupId>

           <artifactId>spring-boot-starter-parentartifactId>

           <version>2.0.1.RELEASEversion>

           <relativePath />

      parent>

 

      <properties>

           <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>

           <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>

           <java.version>1.8java.version>

           <spring-cloud.version>Finchley.RC1spring-cloud.version>

      properties>

      <dependencies>

           <dependency>

                 <groupId>org.springframework.bootgroupId>

                 <artifactId>spring-boot-starterartifactId>

           dependency>

           <dependency>

                 <groupId>org.springframework.cloudgroupId>

                 <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>

           dependency>

           <dependency>

                 <groupId>org.springframework.cloudgroupId>

                 <artifactId>spring-cloud-starter-netflix-ribbonartifactId>

           dependency>

           <dependency>

                 <groupId>org.springframework.cloudgroupId>

                 <artifactId>spring-cloud-starter-netflix-zuulartifactId>

           dependency>

           <dependency>

                 <groupId>org.projectlombokgroupId>

                 <artifactId>lombokartifactId>

                 <optional>trueoptional>

           dependency>

           <dependency>

                 <groupId>com.alibabagroupId>

                 <artifactId>fastjsonartifactId>

                 <version>1.2.3version>

           dependency>

           <dependency>

                 <groupId>org.springframework.bootgroupId>

                 <artifactId>spring-boot-starter-testartifactId>

                 <scope>testscope>

           dependency>

      dependencies>

 

      <dependencyManagement>

           <dependencies>

                 <dependency>

                      <groupId>org.springframework.cloudgroupId>

                      <artifactId>spring-cloud-dependenciesartifactId>

                      <version>${spring-cloud.version}version>

                      <type>pomtype>

                      <scope>importscope>

                 dependency>

           dependencies>

      dependencyManagement>

 

      <build>

           <plugins>

                 <plugin>

                      <groupId>org.springframework.bootgroupId>

                      <artifactId>spring-boot-maven-pluginartifactId>

                 plugin>

                 <plugin>

                      <groupId>org.apache.maven.pluginsgroupId>

                      <artifactId>maven-compiler-pluginartifactId>

                      <configuration>

                            <source>1.8source>

                            <target>1.8target>

                      configuration>

                 plugin>

                 <plugin>

                      <groupId>org.apache.maven.pluginsgroupId>

                      <artifactId>maven-resources-pluginartifactId>

                      <version>3.0.1version>

                      <executions>

                            <execution>

                                  <id>copy-confid>

                                  <phase>packagephase>

                                  <goals>

                                       <goal>copy-resourcesgoal>

                                  goals>

                                  <configuration>

                                       <encoding>UTF-8encoding>

                                        <outputDirectory>${project.build.directory}/ext/confoutputDirectory>

                                       <resources>

                                             <resource>

                                                  <directory>ext/confdirectory>

                                                  <includes>

                                                        <include>logback.xmlinclude>

                                                  includes>

                                                  <filtering>truefiltering>

                                             resource>

                                       resources>

                                  configuration>

                            execution>

                      executions>

                 plugin>

                 <plugin>

                      <groupId>org.jacocogroupId>

                      <artifactId>jacoco-maven-pluginartifactId>

                      <version>0.7.5.201505241946version>

                      <executions>

                            <execution>

                                  <id>default-prepare-agentid>

                                  <goals>

                                       <goal>prepare-agentgoal>

                                  goals>

                            execution>

                            <execution>

                                  <id>default-prepare-agent-integrationid>

                                  <goals>

                                       <goal>prepare-agent-integrationgoal>

                                  goals>

                            execution>

                      executions>

                 plugin>

                 <plugin>

                      <groupId>com.spotifygroupId>

                      <artifactId>docker-maven-pluginartifactId>

                      <version>0.4.3version>

                      <configuration>

                            <imageName>hy_uav_gatewayimageName>

                            <dockerDirectory>src/main/dockerdockerDirectory>

                            <resources>

                                  <resource>

                                       <targetPath>/targetPath>

                                       <directory>${project.build.directory}directory>

                                       <include>${project.build.finalName}.jarinclude>

                                       <include>ext/conf/logback.xmlinclude>

                                  resource>

                            resources>

                      configuration>

                 plugin>

           plugins>

      build>

 

      <repositories>

           <repository>

                 <id>spring-milestonesid>

                 <name>Spring Milestonesname>

                 <url>https://repo.spring.io/milestoneurl>

                 <snapshots>

                      <enabled>falseenabled>

                 snapshots>

           repository>

      repositories>

 配置application 依赖信息

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8100/eureka/

server:

  port: 8769

spring:

  application:

    name: service-zuul

zuul:

  routes:

    api-a:

      path: /api-a/**

      serviceId: itmayiedu_a

    api-b:

      path: /api-b/**

      serviceId: itmayiedu_b

ZuulApplication启动运行

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulApplication {

	public static void main(String[] args) {
		SpringApplication.run(ZuulApplication.class, args);
	}

	@Bean
	public TokenFilter accessFilter() {
		return new TokenFilter();
	}
}

过滤器拦截参数

// 使用网关拦截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"; // 前置过滤器
	}

}

 

你可能感兴趣的:(互联网平台安全设计)