API管理对SOAP的集成&自定义开发者门户 | API Management学习第五篇

前言

本文仅代表作者的个人观点;

本文的内容仅限于技术探讨,不能作为指导生产环境的素材;

本文素材是红帽公司产品技术和手册;

本文分为系列文章,将会有多篇,初步预计将会有26篇。

一、API管理对SOAP集成的两种方法

通常情况下,API管理对web API的集成,除了RESTful Web服务之外,还需要管理基于SOAP的Web服务。

SOAP请求包含带有XML有效负载的HTTP POST请求和一些其他特定于SOAP的标头。 这些SOAP请求可以发送到3scale的APIcast网关,转发到后端SOAP服务,并在没有任何自定义的情况下报告给3scale AMP。

但是,如果还需要收集对后端SOAP服务公开的特定操作的请求,进行一定度量和控制(监控、计费等)则需要进行一些额外的设置。

3 Scale对SOAP的两种集成的方法如下:

  • 创建对Lua和NGINX配置文件的自定义修改,以自动将REST请求映射到SOAP后端
  • 通过OpenShift应用程序上的Fuse进行REST到XML的转换。此时,Fuse应用程序充当后端SOAP服务的RESTful代理,并在SOAP和REST之间进行转换。

二、将SOAP服务部署到OpenShift

在本实验中,我将在与3scale AMP相同的,OpenShift集群中的JBoss企业应用程序平台(EAP)容器上,运行现有的基于SOAP的Java EE应用程序。

SOAP的wsdl文件内容如下: / Stores / src / main / resources / wsdl`。

此WSDL遵循SOAP 1.1规范。

SOAP 1.1规范定义了以下命名空间:http://schemas.xmlsoap.org/wsdl/soap/

SOAP 1.2规范定义了以下命名空间:http://schemas.xmlsoap.org/wsdl/soap12/

SOAP规范的两个版本要求使用不同的机制来调用其WSDL中定义的SOAP操作。 在本实验的后期,在使用3scale管理SOAP服务的上下文中,这两个规范的后果将变得明显。

打开源码 Stores / src / main / java / com / redhat / service / StoresWS.java。

检查SOAP Web服务实现:

为Stores API业务服务应用程序创建一个新项目:

创建模板,通过模板部署应用:

部署成功:

在命令行中,查看Stores服务公开的WSDL:执行以下命令以确定新Stores SOAP服务的WSDL的URL:

通过浏览器访问URL:

在新的浏览器选项卡或窗口中,打开URL“http://wsdlbrowser.com”。

提供Stores WSDL的URL,然后单击Browse。

检查WSDL是否已成功导入,以及页面上是否显示了功能列表:

点击getStore---request是xml

查看result,返回值也是xml

截止到目前,SOAP的应用部署成功,并且能被访问。

三、创建APIcast登台和生产路线

创建从OCP router到 API caststaging和production APIcast的、SOAP应用的路由:

在3scale API中配置

创建新服务:

创建application plan

在RHBank账户中创建app:

集成API:

创建method:

创建metris,以便3 scale进行监控:

配置映射关系:

这样,每次向后端Stores服务的任何SOAP操作发出SOAP请求时,POST请求的映射都将增加StoresWS方法的命中。GET请求的映射将增加对诸如Stores服务的WSDL之类的资源的命中。

设置API测试GET请求:

API测试GET请求:/ StoresWS?wsdl

测试API托管SOAP服务

我们能够使用HTTP客户端通过APIcast网关将SOAP请求发送到后端SOAP服务。

通过APIcast登台URL向Stores服务的WSDL发出curl请求来测试API:

curl -k "https://`oc get route stores-soap-policy-staging-route -o template --template {{.spec.host}} -n $OCP_PROJECT_PREFIX-3scale-amp`/StoresWS?wsdl&user_key=$STORES_SOAP_API_KEY"

对Stores Web Service的getAllStores操作发出POST请求: curl -v -k -X POST --header "Content-Type: application/soap+xml" --header "Accept: application/soap+xml" --header "SOAPAction: http://www.rhmart.com/Stores/getAllStores" -d '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stor="http://www.rhmart.com/Stores/"><soapenv:Header/><soapenv:Body><stor:getAllStores/></soapenv:Body></soapenv:Envelope>' "https://stores-soap-staging-apicast-user11.apps.02bb.openshift.opentlc.com:443/StoresWS?wsdl&user_key=5dac3071cd7ec27c65531882cbfb4fca"

继续使用SOAP 1.1 Web服务,并继续在对该SOAP Web服务的请求中使用名为SOAPAction的HTTP头(上面标黄部分)。

现在,APIcast将使用这些SOAPAction标头字段(: http://www.rhmart.com/Stores/getAllStores)来更新相应的API指标。

选择SOAP,最后结果如下:

单击SOAP策略以展开它。

输入以下映射规则:

四、数据统计 Analytics(分析)

Apicast正确捕获了为每个操作设置的指标。 可以看到endpoint请求的每个SOAPAction对应的命中数。

SOAP 1.2 Web Service的管理类似于您在此处管理SOAP 1.1 Stores Web Service的方法。

不同的地方是:

  • 不要在HTTP请求中设置SOAPAction标头。
  • 在HTTP请求上使用Content-Type标头,并为其action参数设置一个值
  • application / soap + xml Content-Type标头的action参数在SOAP标准的v1.2中指定

使用curl实用程序的示例如下:--header application/soap+xml;charset=UTF-8;action="http://www.rhmart.com/Stores/getAllStores".

五、在OpenShift上使用Fuse进行SOAP转换

在上面的实验中,我们解了3scale如何管理SOAP服务。 在APIcast网关中引入了SOAP策略,以便基于SOAP操作收集指标。

集成SOAP的第二种方法,是使用一个中间层,用于公开REST并转换为SOAP。 JBoss Fuse是实现此目的的理想工具。

接下来,我会部署一个camel,用来公开REST端点并路由到之前部署的SOAP服务。

将Fuse应用程序存储到OpenShift。

过一会,pod创建成功:

检查Fuse中间层:

使用您的登录凭据从Web浏览器登录OpenShift管理控制台。

单击Stores-FIS pod,然后单击Open Java Console:

单击Route Diagram。

期望看到定义的所有Camel路线:

或者,单击“源”并查看Camel路径:

公开REST路由以为Stores API提供的不同SOAP操作提供HTTP方法和URL:

注意getStore和getAllStores的两个GET方法,postStore的POST方法和deleteStore操作的DELETE方法。

每个直接路由对应于REST服务中定义的四个操作:

   <route customId="true" id="createStore">
        <from customId="true" id="_from1" uri="direct:createStore"/>
        <setBody customId="true" id="_setBody1">
            <simple>${body.getStore()}</simple>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader1">
            <constant>createStore</constant>
        </setHeader>
        <to customId="true" id="_to1" uri="direct:soap"/>
    </route>
    <route customId="true" id="deleteStore">
        <from customId="true" id="_from2" uri="direct:deleteStore"/>
        <setBody customId="true" id="_setBody2">
            <simple resultType="int">${header.storeID}</simple>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader2">
            <constant>deleteStore</constant>
        </setHeader>
        <to customId="true" id="_to2" uri="direct:soap"/>
    </route>
    <route customId="true" id="getStore">
        <from customId="true" id="_from3" uri="direct:getStore"/>
        <setBody customId="true" id="_setBody3">
            <simple resultType="int">${header.storeID}</simple>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader3">
            <constant>getStore</constant>
        </setHeader>
        <to customId="true" id="_to3" uri="direct:soap"/>
    </route>
    <route customId="true" id="getAllStores">
        <from customId="true" id="_from4" uri="direct:getAllStores"/>
        <setBody customId="true" id="_setBody4">
            <mvel>new Object[0]</mvel>
        </setBody>
        <setHeader customId="true" headerName="soapMethod" id="_setHeader4">
            <constant>getAllStores</constant>
        </setHeader>
        <to customId="true" id="_to4" uri="direct:soap"/>
    </route>

上面的每个路由都获取请求,构造CXF请求消息对象,并将标头更新到右侧soapMethod以调用SOAP Web服务。

调用SOAP端点的路由:

    <route customId="true" id="soapRoute">
        <from customId="true" id="_from5" uri="direct:soap"/>
        <toD customId="true" id="tod" uri="cxf:bean:wsStores?defaultOperationName=${header.soapMethod}&amp;exchangePattern=InOut"/>
        <setBody customId="true" id="_setBodySoap">
            <simple>${body[0]}</simple>
        </setBody>
        <setHeader customId="true" headerName="Content-Type" id="_setHeaderContextType">
            <constant>application/json</constant>
        </setHeader>
    </route>

在虚拟机中,我们查看FUSE的源代码:

检查项目的application.properties文件中找到的属性:定义了一个名为cxf.endpoint.soap的属性:

jboss@rhtapimgmt ~/lab/3scale_development_labs/StoresFIS (master) $ cat src/main/resources/application.properties

#spring.main.sources=org.mycompany

logging.config=classpath:logback.xml

# the options from org.apache.camel.spring.boot.CamelConfigurationProperties can be configured here

camel.springboot.name=MyCamel

# lets listen on all ports to ensure we can be invoked from the pod IP

server.address=0.0.0.0

management.address=0.0.0.0

# lets use a different management port in case you need to listen to HTTP requests on 8080

management.port=8081

# disable all management endpoints except health

endpoints.enabled = false

endpoints.health.enabled = true

# cxf endpoint address

cxf.endpoint.soap = http://stores-soap:8080

测试Camel REST路由:

将curl请求发送到stores-fis路由以调用REST Web服务,并检查是否已调用SOAP Web服务并将响应转换为application / json:

curl http://`oc get route stores-fis -o template --template {{.spec.host}} -n $OCP_PROJECT_PREFIX-stores-api`/allstores

输出结果是json:

现在可以正确部署REST-SOAP Camel代理,我们可以开始配置APIcast网关以使用此REST端点与SOAP Web服务进行通信。

创建SOAP从router到Stores API staging和production APIcast的路由。:

$ oc create route edge stores-soap-transformation-staging-route \ --service=apicast-staging \ --hostname=stores-staging-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

$ oc create route edge stores-soap-transformation-production-route \ --service=apicast-production \ --hostname=stores-production-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

接下来,在3 scale中配置。

创建service:

创建application plan并publish:

在“开发人员”选项卡中,选择RHBank帐户。

单击Applications,然后单击Create Application。

接下来集成JBoss Fuse Camel REST

对路由发起curl请求,输出结果是Json格式。

jboss@rhtapimgmt / $ curl -k https://stores-staging-apicast-user11.apps.02bb.openshift.opentlc.com:443/allstores?user_key=1f5ad4d8206ff559fe1a6ae0f715b9a4

{"store":[{"storeID":1,"storeName":"Downtown\n Store","storeLat":-34.6052704,"storeLong":-58.3791766},{"storeID":2,"storeName":"EastSide\n Store","storeLat":-34.5975668,"storeLong":-58.3710199},{"storeID":3,"storeName":"?","storeLat":0.0,"storeLong":0.0},{"storeID":4,"storeName":"?","storeLat":0.0,"storeLong":0.0}]}jboss@rhtapimgmt / $

六、OData Service Management

在本节中,我们将部署OData(开放数据协议)服务。 OData是一种标准,它定义了一组用于构建和使用RESTful API的最佳实践。 我们部署的服务基于JBoss Data Virtualization for OpenShift Container Platform虚拟数据库(VDB)。 此VDB具有一个虚拟视图,可从两个数据库表(MySQL和PostgreSQL)中检索数据,并将它们显示为单个SQL ANSI表。 然后,开箱即用,该视图在JBoss Data Virtualization中作为OData REST服务公开。

将Stock API项目部署到OpenShift

在本节中,我们将Stock API部署到在OpenShift上运行的JBoss EAP容器中。 库存数据存在于两个数据库中:MySQL和PostgreSQL。 JBoss Data Virtualization用于提供数据虚拟化,并将组合数据视图显示为OData REST服务。

部署mysql和PostgreSQL(篇幅有限,步骤省略)

对应用发起curl,可以得到正常返回结果。

curl -k http://stock-api-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN/odata4/Stock-API/FederatedStock/stock?$format=JSON

REST odata服务现在已正确部署,现在可以开始配置APIcast网关以使用此REST端点与服务进行通信。

创建APIcast Staging和Production Routes

oc create route edge stock-staging-route \

--service=apicast-staging \

--hostname=stock-staging-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

oc create route edge stock-production-route \

--service=apicast-production \

--hostname=stock-production-apicast-$OCP_PROJECT_PREFIX.$OCP_WILDCARD_DOMAIN

登录3scale,进行配置。

创建app plan并publish:

在“开发人员”选项卡中,单击“RHBank”。

单击Applications,然后单击Create Application:

创建应用:

七、API开发人员注册流程制定:单个应用注册

接下来,我们创建自定义注册流程,以管理通过3scale管理的API的开发人员注册。 涵盖的一些方案是单个应用程序,多个应用程序注册,组成员流程。

达成的目标是:

  • 为Products API应用程序创建API文档
  • 将API文档与3scale API Management集成
  • 创建自定义开发门户
  • 创建客户端应用程序以调用Products API

在3scale内容管理系统(CMS)中找到的开箱即用的主页包含一个嵌入其中的非常简单的注册流程。

在本实验的这一部分中,我们将提取该嵌入式注册流并将其另存为“Partial”。 然后,在您的主页中引用该新Partial。实验中,我们只是将原始注册流逻辑从隐藏在主页中转移到被引用的部分,所以不会改变Developer Portal的外观。

在本实验的后续部分中,我们实现更复杂的注册流程,这些注册流程也实现为部分流程。 只需将引用更改为所需的Partial,即可轻松地将所有注册流程交换到Developer Portal主页中。

在3scale管理员门户中,单击顶部工具栏中的Developer Portal链接以导航到CMS。观察Developer Portal主页的默认外观。在CMS的顶部,单击:访问Developer Portal

导航至:My→Root→homepage:

拷贝代码119 - 182行。

然后新建Partial

修改homepage:

发布两个变更

通过这种方式创建的主业,默认只有两个application plan:

我们要做的是,让主业可以看到所有的application plan:

代码如下:

查看文件:

jboss@rhtapimgmt ~/lab/3scale_development_labs/DevPortal (master) $ cat _single_app_signup_form.html.liquid

<div class="container">

<h1>Pick your plan</h1>

<br/>

{% for service in provider.services %}

<h2> {{ service.name }} </h2>

<div class="row">

{% for plan in service.application_plans%}

<div class="col-md-4">

<article class="panel panel-default">

<div class="panel-heading">

<strong>{{ plan.name }}</strong>

</div>

<div class="panel-body">

<div class="row">

{% if plan.features == present %}

<div class="col-md-6">

<h5>Features</h5>

<ul class="features list-unstyled">

{% for feature in plan.features %}

<li>

<i class="fa fa-check"></i> {{ feature.name }}

</li>

{% endfor %}

</ul>

</div>

{% endif %}

<div class="col-md-6">

<h5>Limits</h5>

<ul class="limits list-unstyled">

{% if plan.usage_limits == present %} {% for limit in plan.usage_limits %}

<li>

<i class="fa fa-signal"></i> {{ limit.metric.name }} &ndash; {{ limit.value }} {{ limit.metric.unit }}s per {{ limit.period }}

</li>

{% endfor %} {% else %}

<li>

<i class="fa fa-signal"></i> No limits

</li>

{% endif %}

</ul>

</div>

</div>

</div>

<div class="panel-footer">

<div class="row">

<div class="col-md-12">

<a class="btn btn-cta-secondary pull-right" href="{{ urls.signup }}?{{ plan | to_param }}&{{ service.service_plans.first | to_param }}">Signup to plan {{ plan.name }}</a>

</div>

</div>

</div>

</article>

</div>

{% endfor %}

</div>

{% endfor %}

</div>

将此partial添加到开发人员门户。

编辑主页:

在第120行附近,将original_app_signup_form替换为single_app_signup_form。

现在点击访问开发者门户,此时可以看到所有的application plan:

八、API开发人员注册流程制定:单个应用注册

多应用程序注册流程允许用户同时注册多个服务(以及相关的application paln)。它通过提供在Developer Portal中呈现多选复选框HTML表单的部分来实现。

确保“多个应用程序”功能被启用

参照源码:

$ cat _multiple_app_signup_form.html.liquid

<form action="{{ urls.signup }}" method="get">

<div class="container">

<h1>Pick your plan</h1>

<br/>

{% for service in provider.services %}

<h2> {{ service.name }} </h2>

<div class="row">

{% for plan in service.application_plans%}

<div class="col-md-4">

<article class="panel panel-default">

<div class="panel-heading">

<strong>{{ plan.name }}</strong>

</div>

<div class="panel-body">

<div class="row">

{% if plan.features == present %}

<div class="col-md-6">

<h5>Features</h5>

<ul class="features list-unstyled">

{% for feature in plan.features %}

<li>

<i class="fa fa-check"></i> {{ feature.name }}

</li>

{% endfor %}

</ul>

</div>

{% endif %}

<div class="col-md-6">

<h5>Limits</h5>

<ul class="limits list-unstyled">

{% if plan.usage_limits == present %} {% for limit in plan.usage_limits %}

<li>

<i class="fa fa-signal"></i> {{ limit.metric.name }} &ndash; {{ limit.value }} {{ limit.metric.unit }}s per {{ limit.period }}

</li>

{% endfor %} {% else %}

<li>

<i class="fa fa-signal"></i> No limits

</li>

{% endif %}

</ul>

</div>

</div>

</div>

<div class="panel-footer">

<div class="row">

<div class="col-md-12">

<div class="row">

<div class="col-md-12">

<input type="checkbox" name="plan_ids[]" value="{{ plan.id }}">Signup to {{ plan.name }}</input>

<input type="hidden" name="plan_ids[]" value="{{ service.service_plans.first.id }}"></input>

</div>

</div>

</div>

</div>

</div>

</article>

</div>

{% endfor %}

</div>

{% endfor %}

<div class="container text-center">

<button type="submit" class="btn btn-cta-primary">Signup</a>

</div>

</div>

</form>

创建:multi_app_signup_form partial。

修改homepage:

修改成:

发布变更后,登录开发者界面,可以看到application plan的复选框:

我们选择两个app plan,API Unlimited 和ProductsBasicPlan,注册账户:

然后到admin门户激活:

然后用新建的账户登录开发者界面,可以看到两个应用。

魏新宇

  • 红帽资深解决方案架构师
  • 专注开源云计算、容器及自动化运维在金融行业的推广
  • 拥有MBA、ITIL V3、Cobit5、C-STAR、TOGAF9.1(鉴定级)等管理认证。
  • 拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、AIX、HPUX等技术认证。

原文发布于微信公众号 - 大魏分享(david-share)

原文发表时间:2018-07-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据和云

修而未复:说说WebLogic那修不完的Java反序列化漏洞

编者说明:这篇文章初稿写在Oracle CPU补丁发布之后,考虑到文章内容的影响,并未在当时发布,WebLogic 的 Java 反序列化漏洞,已经修复了多次,...

2346
来自专栏FreeBuf

Metasploitable2使用指南

Metasploitable 2 Metasploitable2 虚拟系统是一个特别制作的ubuntu操作系统,本身设计作为安全工具测试和演示常见漏洞攻击。版...

5549
来自专栏人工智能LeadAI

配置深度学习主机与环境(TensorFlow+1080Ti) | 第二章 Win10&Ubuntu双系统与显卡驱动安装

网上安装双系统的教程不少,但多数教程所使用的硬件以现在的眼光看来显得有些过时;另外,其原有所使用的方法,对于新的硬件也不再合适。本教程写于2017年7月,希望能...

6616
来自专栏小白课代表

简洁平凡的PC清理工具——CCleaner

3076
来自专栏木子昭的博客

迈出黑客第一步, 安装配置Kali虚拟机

? Kali Kali是一套用于安全渗透(黑客)的Linux发行版, 好处在于, 系统内置了大量的安全渗透方面的软件, 新手可以免于配置, 开...

4486
来自专栏aoho求索

认证鉴权与API权限控制在微服务架构中的设计与实现(一)

引言: 本文系《认证鉴权与API权限控制在微服务架构中的设计与实现》系列的第一篇,本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现。 1. 背景 ...

6616
来自专栏kl的专栏

spring boot动态调整线上日志级别

日志模块是每个项目中必须的,用来记录程序运行中的相关信息。一般在开发环境下使用DEBUG级别的日志输出,为了方便查看问题,而在线上一般都使用INFO级别的日志,...

6216
来自专栏后端云

实时操作系统

一般的linux都是GPOS(通用)内核。GPOS是不保证实时的,但是对于大多数应用程序来说是没有问题的。GPOS可以充分利用物理资源。但在实时性要求性比较高的...

2887
来自专栏解Bug之路

解Bug之路-Druid的Bug 原

笔者很热衷于解决Bug,同时比较擅长(网络/协议)部分,所以经常被唤去解决一些网络IO方面的Bug。现在就挑一个案例出来,写出分析思路,以飨读者,希望读者在以后...

1535
来自专栏walterlv - 吕毅的博客

制作 Windows 10 安装盘,解决大于 4GB 的 Windows 10 镜像在 UEFI 模式下的安装问题

2018-02-22 14:14

2731

扫码关注云+社区

领取腾讯云代金券