# Gravitee

本项目基于gravitee-am-2.5.0以及gravitee-apim-1.25.1进行构建部署。

# Gravitee介绍

Gravitee由两个核心模块组成,分别是access manager模块(am),api manager模块(apim),其中am模块又分为前端控制台模块,后端服务模块,am-gateway网关模块。apim模块同样也分为前端控制台模块,后端服务模块,apim-gateway网关模块。

# am模块介绍

am(access manager认证管理)模块旨在成为应用程序和身份提供商之间的桥梁,以验证、授权和获取有关用户帐户的信息。它依赖于不同的协议,如OAuth2和OpenId Connect,并支持许多身份验证/身份验证提供商,这要归功于一个插件系统,该系统可以专门化平台行为,以完全满足您的需求。

# 前端模块

am的前端模块需要部署在web服务器中,一般推荐使用nginx进行部署即可。

[root@test215156 graviteeio-am-management-ui-2.5.0]# ls
3rdpartylicenses.txt                 data-table.bce071e976865da51100.eot          main.ed6a43348c2d8637b483.bundle.js               polyfills.e1046bde851223c91182.bundle.js
assets                               favicon.ico                                  MaterialIcons-Regular.012cf6a10129e2275d79.woff   styles.a91a26e8db93fb34e99e.bundle.css
build.json                           gravitee_logo_anim.4692fbacbef919061ecf.gif  MaterialIcons-Regular.570eb83859dc23dd0eec.woff2
constants.json                       index.html                                   MaterialIcons-Regular.a37b0c01c0baf1888ca8.ttf
data-table.b0aebd744ce7adb780a9.svg  inline.ea87f7616d87e2be1603.bundle.js        MaterialIcons-Regular.e79bfd88537def476913.eot

Nginx的关键配置如下:

server {
    # 监听8090端口
    listen       8090;
    server_name  127.0.0.1;

    location / {
        root   /app/gravitee/graviteeio-am-full-2.5.0/graviteeio-am-management-ui-2.5.0;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

前端页面访问效果如下:

# 后端服务模块

am后端服务是java进程,该进程会启动两个web服务,分别占用8093端口以及18093端口,其中8093端口与前端服务一起构成access manager服务,18093服务端口则是用于services服务(直接通过请求调用)。


# am-gateway模块

am-gateway服务是java进程,该进程会启动两个web服务,分别占用8092端口以及18092端口,其中8092端口用于身份认证,18092端口则是用于services服务(直接通过请求调用)。


# apim模块介绍

apim是一个灵活、轻量级和一流的开源API管理解决方案,可帮助您和您的组织控制用户访问您的API的人员、时间和方式。apim不仅仅是一个简单的产品,它还是API管理的全球解决方案。

# 前端模块

apim的前端模块需要部署在web服务器中,一般推荐使用nginx进行部署即可。

[root@test215156 graviteeio-management-ui-1.25.1]# ls
12b4add22c30991abc3ab500c3baad56.eot    a0180954d7d374e153899d0974b25225.svg  e18bbf611f2a2e43afc071aa2f4e1512.ttf   postcss.config.js
23d975197178d5c83c18c07601bce51a.png    app-f1badcb67b2d451d5e28.js           f4769f9bdb7466be65088239c12046d1.eot   swagger-oauth2-redirect.html
30dd0f529e5155cab8a1aefa4716de7f.png    assets                                fa2772327f55d8198301fdb8bcfc8158.woff  themes
448c34a56d699c29117adc64c43affeb.woff2  b4361244b610df3a6c728a26a49f782b.png  favicon.ico                            vendor-f1badcb67b2d451d5e28.js
6ba6c64f55a7902a4b77781f82b5a3fb.svg    build.json                            index-f1badcb67b2d451d5e28.css         vendors~app-f1badcb67b2d451d5e28.js
71229ba79b00c595b37c3744e6fb8622.ttf    c458b32c30f192bce281b7b667780142.svg  index.html                             vendors~app~vendor-f1badcb67b2d451d5e28.js
77c921ab285376aff72fbdd2d0784e0b.png    constants.json                        libraries                              vendors~vendor-f1badcb67b2d451d5e28.js
89889688147bd7575d6327160d64e760.svg    docs                                  portal

Nginx的关键配置如下:

server {
    # 监听8080端口
    listen       8080;
    server_name  127.0.0.1;

    location / {
        root   /app/gravitee/graviteeio-full-1.25.1/graviteeio-management-ui-1.25.1;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

前端页面访问效果如下:

# 后端服务模块

apim后端服务是java进程,该进程会启动两个web服务,分别占用8083端口以及18083端口,其中8083端口与前端服务一起构成api manager服务,18083服务端口则是用于services服务(直接通过请求调用)。


# apim-gateway模块

apim-gateway服务是java进程,该进程会启动两个web服务,分别占用8082端口以及18082端口,其中8082端口用于提供网关服务,18082端口则是用于services服务(直接通过请求调用)。


# Access Manager

Access Manager由Domain,Client,Provider等核心模块组成

# Domain安全域

安全域将允许您创建客户端(client)、注册用户(users)和管理身份提供者(identity providers),以提供集中的身份验证、授权和用户管理。

# 图形界面上创建安全域

1.进入http://127.0.0.1:8090/am/admin/login登录页面,输入管理员账号:admin 密码:adminadmin登录系统。

2.点击右侧用户菜单中的Global settings模块。

3.在domains页面点击(+)按钮添加新的安全域。

4.为你的安全域添加名称,描述后点击创建按钮。

5.点击"click here"按钮使新创建的安全域生效。

6.重新点击Global settings模块,可以看到新创建的安全域生效。

7.点击domians页面上domain的齿轮按钮可以管理domain。

8.点击"DELETE"按钮可以删除domain(这里点击删除onecloud这个domain验证下面的接口方式创建安全域流程)。

# 接口方式创建安全域

1.通过登录接口生成access_token。
使用管理员的控制台页面http://127.0.0.1:8093/admin/login,输入用户名以及密码登录。

登录完成后,找到截图中的部分复制出来,其中的"Bearer eyJhbGciOiJIUzI1NiJ9.***"就是我们接下来要使用的access_token参数了。

2.通过接口请求调用domain创建接口。

curl -X POST \
  http://10.6.215.156:8093/management/domains \
  -H 'Accept: */*' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.***' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Host: 10.6.215.156:8093' \
  -H 'Postman-Token: addf3a2a-f7c2-4586-9490-74dbdb401bc5,dbc04ec8-6950-4d8c-959c-eae254b9e5c9' \
  -H 'User-Agent: PostmanRuntime/7.13.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache' \
  -H 'content-length: 64' \
  -d '{
    "name": "onecloud",
    "description": "onecloud domain"
}'

可以看到此时domain创建完成,但是状态还不是有效状态。

3.调用接口使创建的domain生效。

# 需要特别注意,这个接口使用的是PUT这种提交方式。
curl -X PUT \
  http://10.6.215.156:8093/management/domains/onecloud \
  -H 'Accept: */*' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.***' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Host: 10.6.215.156:8093' \
  -H 'Postman-Token: a79b75e7-2d73-4618-bbb5-b55e67a174a2,ff915b1c-01c5-4bb1-95a2-ca5bc8f563a9' \
  -H 'User-Agent: PostmanRuntime/7.13.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache' \
  -H 'content-length: 23' \
  -d '{
    "enabled": true
}'

可以看到此时domain是有效状态。

# Client客户端

在与AM授权网关(AM Authorization Gateway)交互之前,必须创建一个客户端(Client)。客户端代表您的应用程序,并将为您提供登录、授权、身份验证和身份管理所需的信息(如客户端ID/客户端机密)。应用程序可以是本地移动应用程序、单页前端web应用程序,也可以是在服务器上执行的常规web应用程序。

# 图形界面上创建Client

在安全域domain的clients页面,点击页面上的"+"号创建应用(client)。

输入clientId,clientSecret,clientName后,点击"CREATE"按钮即可创建client。

客户端client创建完成后,可以配置客户端的OAuth2鉴权请求方式(Grant Type)及获取鉴权结果(Response types)。

# 接口方式创建Client

curl -X POST \
  http://10.6.215.156:8093/management/domains/onecloud/clients \
  -H 'Accept: */*' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.***' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Host: 10.6.215.156:8093' \
  -H 'Postman-Token: 96e77b25-0675-4883-8c18-95f0ee3de433,052db799-1de7-4d1f-894b-0e820ff720a9' \
  -H 'User-Agent: PostmanRuntime/7.13.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache' \
  -H 'content-length: 89' \
  -d '{
  "clientId": "file1",
  "clientSecret": "file1",
  "clientName": "文件服务1"
}'

可以看到,使用接口也可以创建client。

点击client详情页的"DELETE"按钮,可以删除client。

# 使用OAuth2测试应用鉴权

在client创建完成后,我们可以使用OAuth2验证相关的鉴权是否可用(这里以file文件服务为例进行说明)。

有三种鉴权方式可以供我们选择,这里我们使用"client_credentials"这种方式获取鉴权,调用如下接口即可:

curl -X POST \
  'http://10.6.215.156:8092/onecloud/oauth/token?grant_type=client_credentials&client_id=file&client_secret=file' \
  -H 'Accept: */*' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: 10.6.215.156:8092' \
  -H 'Postman-Token: cb85f7bb-8b97-4d20-9607-b0f2bfdd6068,b16112bf-5a6a-4f9f-a169-7a2304fd80d8' \
  -H 'User-Agent: PostmanRuntime/7.13.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache' \
  -H 'content-length: '


可以看到该接口成功生成了jwt token,同时返回了token的过期时间,图中是7199秒,与client页面上的过期时间一致。

同时将该jwt token放到解析网站上,我们可以看到这个token的必要信息,如下图:

# 为client开启provider鉴权

这里以file这个client为例,演示为client开启provider鉴权。

# Provider身份提供者

身份提供者对用用户组的概念,每一个用户组下有多个用户,Client可以开启身份提供者校验功能,如开启该功能,服务请求方除了携带自己的clientid,secretid外,还必须携带用户的用户名以及密码才能通过am gateway的校验。也有可能是该provider组里的用户才能在这个client上配置接口(目前阶段个人理解)。

# Provider创建

这里我们先不关注provider的创建,仅使用默认组。

# User用户

# 创建用户User

在Domain中点击User页签,切换到User页面,点击页面上的"+"号按钮创建用户。

一个用户一定从属于且只从属于一个Provider组,用户可以归属于一个Client,也可以不归属到任何Client中(Client下的用户可以操作邮件),这里不给该用户分配从属的Client。

# 使用User获取鉴权

curl -X POST \
  'http://10.6.215.156:8092/onecloud/oauth/token?grant_type=password&client_id=file&client_secret=file&username=xuhaodi&password=xhd@holick2024' \
  -H 'Accept: */*' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: 10.6.215.156:8092' \
  -H 'Postman-Token: 608b068f-acc2-4c97-bd28-e054860e2aa6,e4a69e8e-47b3-4c8d-ad03-4638b25d126f' \
  -H 'User-Agent: PostmanRuntime/7.13.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache' \
  -H 'content-length: '

可以看到,该对应用户成功获取到鉴权信息:

# 解析token获取用户信息

curl -X GET \
  http://10.6.215.156:8092/onecloud/oidc/userinfo \
  -H 'Accept: */*' \
  -H 'Authorization: Bearer eyJraWQiOiJkZWZhdWx0LWdyYXZpdGVlLUFNLWtleSIsImFsZyI6IkhTMjU2In0.eyJzdWIiOiI0NGQ2YzcwZC00ZmE0LTQ3YTEtOTZjNy0wZDRmYTQ0N2ExNjAiLCJhdWQiOiJmaWxlIiwiZG9tYWluIjoib25lY2xvdWQiLCJzY29wZSI6Im9wZW5pZCIsImlzcyI6Imh0dHA6Ly8xMC42LjIxNS4xNTY6ODA5Mi9vbmVjbG91ZC9vaWRjIiwiZXhwIjoxNzA3MjIwODMyLCJpYXQiOjE3MDcyMTM2MzIsImp0aSI6ImN1bEROcHdQQUFqdHN3bFJ0NGI2OEhLd3Q0QSJ9.8FRD9IiUBNW7BC2BzcJY83UK8w4YUV0xdx4K-l5yUDY' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: 10.6.215.156:8092' \
  -H 'Postman-Token: ae270579-e12b-4025-b482-163638572463,3138dab5-0aac-4566-b848-7e56fff1754a' \
  -H 'User-Agent: PostmanRuntime/7.13.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache'

可以看到,成功通过token解析到用户信息:

# API Management

API Management负责API的发布以及订阅。

# 创建API

# 通过门户页面protal创建API

找不到官网上和门户页有关的文档,只能通过一些操作查找到相关的信息(这里可以看到门户页用的是domain为onelife的安全域,client为apim的客户端在访问,按说onecloud安全域的相关client也可以添加门户页访问)。

# 通过管理页面创建API

使用admin账户登录apim管理页面。

点击api创建按钮,创建新的api。

填写API名称,版本,上下文路径Context-path后点击Next按钮。

添加API提供者的原始地址(endpoint)后,点击NEXT。

这里先不填写API的Plans(API保护策略),以及Docs(API参考文档),点击SKIP。


点击按钮,这里我们仅创建API,并不发布。

# 发布API

在API正式发布之前,我们需要完成Resources以及Plans的配置。

# 配置Resources

找到我们新创建的API,点击Desgin按钮,切换到API Design页面。

点击Resources按钮,切换到Resources页面。

点击页面上的加号按钮,添加新的Resource。

填写Resource的相关信息后点击SAVE创建。


# 创建Plans

找到Plans页面,点击页面上的加号按钮,创建新的Plan。

填写Plan的名称以及描述。

选择Plan的鉴权方式为OAuth2,同时填写对应的Resource名称后一直点下一步即可完成Plan的创建。

刚创建完成的Plan是未发布状态,需要点击发布按钮,发布Plan。

# 订阅API

每一个API在发布后,订阅之前,都要求必须配备Plans(保护策略),只有受信任的应用程序才能通过请求API密钥来访问API数据。

# 创建Application

这里创建的application基于onelife安全域,每一个创建的application需要有一个am中onelife安全域的client对应,有且只有一个对应。

# 订阅API

找到已经发布的API,点击Subscriptions页上面的加号按钮,开始订阅API。

选择Application以及API Plan后点击CREATE。

可以看到,该Application成功订阅了接口。

# 使用API

# 生成鉴权token

参考用户认证,获取登录所需的token信息。

# 使用token调用接口

在API页面,找到对应的API的调用地址,然后访问。

通过如下接口调用API:

curl -X GET \
  'http://10.6.215.156/apim/api/v1/extquery/overViewPlcInfo2?plcno=8109336183' \
  -H 'Accept: */*' \
  -H 'Authorization: Bearer eyJraWQiOiJkZWZhdWx0LWdyYXZpdGVlLUFNLWtleSIsImFsZyI6IkhTMjU2In0.***' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: 10.6.215.156' \
  -H 'Postman-Token: 43fe2191-c5eb-4aac-bed4-031502232df0,a2955e3c-4e39-475c-8a32-47642553702c' \
  -H 'User-Agent: PostmanRuntime/7.13.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache'

可以看到,API调用完成,获取到了接口提供方的数据。

# 部署架构

这里仅附上部署架构图。

# API网关能用来做什么?

API网关可以用来做分布式登录鉴权,CORS同源跨域问题处理,限流熔断,应用流量分析。