Начало работы с Kong Gateway

задняя часть

Знакомство с Конгом

Kong — это высокодоступный API-интерфейс шлюза, написанный на основе модуля Nginx_Lua, который равномерно распределяет запросы на каждый сервер с помощью конфигурации предварительной балансировки нагрузки для обработки большого количества сетевых запросов. Основываясь на функциях Nginx, сам Kong также очень легко масштабируется на несколько серверов.

Конг состоит из трех основных компонентов:

Kong Server :基于nginx的服务器,用来接收API请求。
Apache Cassandra/PostgreSQL :用来存储操作数据。
Kong dashboard:官方推荐UI管理工具,也可以使用 restfull 方式 管理admin api。

Как работает Конг

Основные понятия Конга:

客户端:指下游客户向Kong的代理端口发出请求。
服务:服务实体,是对自己的每个上游服务的抽象。客户请求被转发到该服务。
路由:路由是进入Kong的入口点,并为要匹配的请求定义规则,并路由到给定的Service。服务和路由之间的关系是一对多的关系。
插件:它是在代理生命周期中运行的业务逻辑。可以通过ADMIN API配置插件 - 全局(所有传入流量)或特定的路由和服务。
用户:是调用API 服务时身份认证的凭据

Дополнительная ссылка на контентОфициальный сайт konghq.com/kong/

Конфигурация установки

На этот раз установка основана на докере. Для установки Docker см.Docker практикует одну установку Docker

1. Создайте виртуальную сеть в Docker:

docker network create kong-net

Последующие приложения и базы данных используют эту виртуальную сеть.

2. Напишите docker-compose.yaml

version: "3.7"
services: 
  kong:
    # 镜像版本,目前最新
    image: kong:1.1.2
    environment:
    # 数据持久化方式,使用postgres数据库
     - "KONG_DATABASE=postgres"
    # 数据库容器名称,Kong连接数据时使用些名称
     - "KONG_PG_HOST=kong-database"
    # 数据库名称
     - "KONG_CASSANDRA_CONTACT_POINTS=kong-database"
    # 日志记录目录
     - "KONG_PROXY_ACCESS_LOG=/dev/stdout"
     - "KONG_ADMIN_ACCESS_LOG=/dev/stdout"
     - "KONG_PROXY_ERROR_LOG=/dev/stderr"
     - "KONG_ADMIN_ERROR_LOG=/dev/stderr"
    # 暴露的端口
     - "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl"
    ports:
     - 8000:8000
     - 8443:8443
     - 8001:8001
     - 8444:8444
    # 使用docker网络
    networks:
     - kong-net
 
    # 依赖数据库服务
    depends_on:
      - kong-database
# kong 管理界面
  konga:
    image: pantsel/konga
    environment:
     - "TOKEN_SECRET=51liveup.cn"
     - "NODE_ENV=production"
    ports:
     - 8080:1337
    networks:
     - kong-net
 
    depends_on:
      - kong-database
      - 
# 数据库服务
  kong-database:
    image: postgres:9.6
    ports:
      - "5432:5432"
    environment:
    # 访问数据库的用户
      - POSTGRES_USER=kong
      - POSTGRES_DB=kong
    networks:
      - kong-net
    volumes:
    # 同步时间
      - /etc/localtime:/etc/localtime:ro
    # 数据库持久化目录
      - /data/data/postgresql:/var/lib/postgresql/data
 
networks:
  kong-net:
    external: true

Запустите службу с помощью команды docker-compose up. Вы обнаружите ошибку базы данных при запуске, потому что данные postgres, используемые kong, все еще должны быть инициализированы, прежде чем их можно будет использовать.

3. Инициализировать базу данных

docker run --rm \
     --network=kong-net \
     -e "KONG_DATABASE=postgres" \
     -e "KONG_PG_HOST=kong-database" \
     -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
     kong:latest kong migrations bootstrap

Обязательно инициализируйте базу данных после создания контейнера базы данных и оставьте контейнер Docker базы данных работающим.После успешной инициализации базы данных используйте команду docker-compose up -d, чтобы снова запустить службу.

Проверить установку

Выполнить на хосте

curl -i http://localhost:8001/

Возвращает следующее:

HTTP/1.1 200 OK
Date: Mon, 17 Jun 2019 02:43:33 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/1.1.2
Content-Length: 5860
 
 
....

Указывает на правильность установки. Kong можно использовать как обычно.

доступhttp://localhost:8080Чтобы получить доступ к интерфейсу управления Konga, вам необходимо создать учетную запись администратора и пароль для первого входа в систему.

Для получения дополнительной информации см.Документация по установке на официальном сайте.

настроить экземпляр

настроить доступwww.baidu.com/API интерфейса будет подключен к серверному адресу интерфейса бизнес-данных при фактическом использовании.

1. Создайте сервис

Служба — это абстракция вышестоящей службы, которая может быть приложением или определенным интерфейсом.

Создайте сервис из командной строки:

curl -i -X POST \
--url http://51liveup.cn:8001/services/ \
--data 'name=baidu-service' \
--data 'url=https://www.baidu.com/'

Интерфейс управления Konga для создания и просмотра сервисов показан ниже.

2. Создайте маршрут

Создайте маршрут на только что созданном сервисе baidu-service.

curl -i -X POST \
--url http://51liveup.cn:8001/services/baidu-service/routes \
--data 'hosts[]=baidu.com' \
--data 'paths[]=/api/baidu'

3. Доступ к данным через Postman

Обратите внимание: если адрес, предоставленный API, не соответствует адресу, определенному предыдущим хостом (baidu.com), вам необходимо добавить параметр Host=baidu.com в заголовки запроса.

Использование JWT-плагина

В приведенной выше конфигурации, если вы знаете адрес маршрутизатора, вы можете получить доступ и получить данные.Нам нужно добавить API к аутентификации. Если API обращен не к конкретному пользователю, а к другим системам, JWT можно использовать для межсистемной аутентификации, а для выполнения этой функции можно использовать подключаемый модуль Kong JWT. Плагин JWT должен быть включен на соответствующем маршрутизаторе.

curl -X POST http://51liveup.cn:8001/routes/fee36521-e549-410f-8986-9fbba02219c1/plugins \
    --data "name=jwt"

fee36521-e549-410f-8986-9fbba02219c1 — идентификатор созданного маршрутизатора.

В это время доступ к вышеуказанному интерфейсу через Postman предложит:

{
    "message": "Unauthorized"
}

Клиент должен предоставить информацию для аутентификации JWT, чтобы получить к ней доступ.

Создать пользователя

curl -i -X POST \
--url http://51liveup.cn:8001/consumers/  \
--data "username=baiduuser"

Пользователь создает учетные данные JWT

curl -i -X POST \
--url http://51liveup.cn:8001/consumers/baiduuser/jwt \
--header "Content-Type: application/x-www-form-urlencoded"

Возвращает учетную информацию, вы также можете запросить учетную информацию с помощью метода get

{
    "rsa_public_key": null,
    "created_at": 1560723665,
    "consumer": {
        "id": "8bb94f49-22a6-4d77-9a64-21f13adc0342"
    },
    "id": "a110d234-6dc1-4443-9da2-21acddc66e09",
    "algorithm": "HS256",
    "secret": "lCe8Lbb7F0KtLccaBcBnOvYg76V7wmQx",
    "key": "7yQoUdF0aFUC9N593uLQLbqL7RSPj2qM"
}

Используйте ключ и секрет вjwt.io/Может генерировать учетные данные jwt.

Потом доступ через почтальона, можно посмотреть данные.

Ниже приведен пример доступа к данным через код Java.НепригодныйИнтерфейс baidu настроен выше.

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import okhttp3.*;
 
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Base64;
 
public class Example {
 
    public static void main(String[] args) {
        Example example = new Example();
        example.get("http://51liveup.cn:8000/api/xxxx/1");
    }
 
    public void get(String url) {
        OkHttpClient mOkHttpClient = new OkHttpClient();
        Request request = createBuilder().url(url).post(FormBody.create(MediaType.parse("application/json; charset=utf-8"), "{}")).build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                System.out.println("failure : \r\n" + e);
            }
 
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                System.out.println("response:");
                System.out.println(response.body().string());
            }
        });
    }
 
    private Request.Builder createBuilder() {
        Request.Builder builder = new Request.Builder();
        builder.addHeader("host", "51liveup.cn");
        builder.addHeader("Authorization", "Bearer " + generateJwt());
        return builder;
    }
 
    private String generateJwt() {
        String jwt = Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setIssuer("7yQoUdF0aFUC9N593uLQLbqL7RSPj2qM")  // key
                .signWith(SignatureAlgorithm.HS256, Base64.getEncoder().encodeToString("lCe8Lbb7F0KtLccaBcBnOvYg76V7wmQx".getBytes(Charset.forName("utf-8"))))
                .compact();
        System.out.println("jwt:" + jwt);
        return jwt;
    }
}

Использование плагина ACL

Плагин JWT может защитить API от доступа доверенных пользователей, но не может различить, какой пользователь может получить доступ к какому API, то есть проблема интерфейсных разрешений.Для решения этой проблемы мы используем плагин ACL.

Включите плагин acl на указанном выше маршруте, укажите белый список,

curl -i -X POST \
--url http://51liveup.cn:8001/routes/afb8bfbd-977e-464f-8c94-05d6c5c98429/plugins \
--data "name=acl"  \
--data "config.whitelist=baiduGroup"

В это время, если вы снова получите доступ к API, вам будет предложено, чтобы служба не была доступна.

{
    "message": "You cannot consume this service"
}

Просто привяжите пользователя baiduuser к группе baiduGroup в белом списке.

curl -i -X POST \
--url http://localhost:8001/consumers/tianqiuser/acls \
--data "group=tianqi"

Снова получите доступ к интерфейсу, и данные могут быть возвращены в обычном режиме.

Теперь вы можете выполнять аутентификацию и контроль разрешений на интерфейсе, предоставляемом шлюзом.