Проверка передаваемого содержимого#

Одной из основных задач SOWA является проверка пакетов, передаваемых через SOWA на соответствие схемам валидации (для структурированных данных в форматах JSON/XML), а также поиск потенциальных инъекций как в содержимом, так и в заголовках запросов и ответов.

Валидация JSON#

Подключение валидации на примере JSON сообщений.

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

Для POST запросов это будет схема для запроса:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "data": {
      "type": "string"
    },
    "value": {
      "type": "number"
    }
  },
  "required": [
    "data"
  ]
}

Для GET это будет схема для ответа:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "message": {
      "type": "string"
    },
    "result": {
      "type": "number"
    }
  },
  "required": [
    "message", "result"
  ]
}

Создайте профиль json_validation:

[sowacfg@tkle-ish0038 proxies]$ sowa-config --add-profile json_validation
Profile "json_validation" was successfully created

Также создайте файлы postReq.json и getResp.json, в которые поместите созданные схемы.

Скопируйте данные файлы в папку /schemes, которую создайте в ресурсной папке профиля:

mkdir /sowa/profile_storage/custom/json_validation/schemes
cp schemes/postReq.json /sowa/profile_storage/custom/json_validation/schemes
cp schemes/getResp.json /sowa/profile_storage/custom/json_validation/schemes

Создайте конфигурационный файл профиля json_validation со следующим содержимым:

profile: json_validation
version: 2.0.3
system:
  wrk_count: 1
  conn_count: 4096
  optional:
    log_level: error
service:
  service_http_proxy:
    - id: 1
      listen:
        - port: 11111
      url: ^/validateMe
      allowed_queries:
        - method: get
        - method: post
      chains:
        request_chains:
          - message: $clj_request_body
            actions:
              - action: JsonValidation
                params:
                  validation_schema:
                    path: schemes/postReq.json
                    type: file
                conditions:
                  - var: $request_method
                    operator: '='
                    val: POST
        response_chains:
          - message: $clj_response_body
            actions:
              - action: JsonValidation
                params:
                  validation_schema:
                    path: schemes/getResp.json
                    type: file
                conditions:
                  - var: $request_method
                    operator: '='
                    val: GET
      upstream_group_id: back_1
      upstream_groups:
        - id: back_1
          servers:
            - server: 127.0.0.1:10025

Как видно из конфигурации, за валидацию отвечает секция цепочек (chains), в которой можно настроить сообщение (message), которое будет проверяться и цепочки действий над ним (actions).

В каждом действии необходимо задать параметры(parameters) и условия(conditions) его применения

К примеру, для валидации нашего сообщения мы использовали действие JsonValidation, в котором задали

  • параметр validation_schema — относительный путь к файлу со схемой валидации;

  • условия применения в conditions - в нашем случае, метод запроса

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

        response_chains:
          - message: $clj_response_body
            actions:
              - action: JsonValidation
                params:
                  validation_schema:
                    path: schemes/getResp.json
                    type: file
                conditions:
                  - var: $request_method
                    operator: '='
                    val: GET
                  - var: $upstream_status
                    operator: '='
                    val: 200

То есть здесь было указано, что валидация по схеме getResp.json будет выполняться только для ответов со статусом 200. Внесите данное ограничение в конфигурацию профиля и выполните конфигурацию.

Далее, в сервисы заглушек добавьте заглушку, которая будет возвращать json-ответ.

- id: hello_json
  optional:
    response_code: 200
    response_body: "{\"message\": \"my message\", \"result\": 0}"
  response_headers:
    - name: Content-Type
      value: application/json
  url: ^/validateMe
  listen:
   - port: 10025

Сконфигурируйте заглушку и запустите ее.

[sowacfg@tkle-ish0038 proxies]$ sowa-config --config ../stubs/sample_stub.yml
Profile sample_stub is running. Are you sure that you want to reconfigure? [y/n] y
Profile "sample_stub" was successfully configured.
[sowacfg@tkle-ish0038 proxies]$ sowa-config --stop sample_stub
Profile "sample_stub" was successfully stopped.
[sowacfg@tkle-ish0038 proxies]$ sowa-config --run sample_stub
Profile "sample_stub" was successfully started.

И запустите профиль json_validation.

Отправьте корректный POST-запрос:

[sowacfg@tkle-ish0038 proxies]$ curl -v --data "{"data": "data"}" http://localhost:11111/validateMe
* About to connect() to localhost port 11111 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11111 (#0)
> POST /validateMe HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11111
> Accept: */*
> Content-Length: 12
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 12 out of 12 bytes
< HTTP/1.1 200 OK
< Date: Tue, 06 Apr 2021 13:02:48 GMT
< Content-Type: application/json
< Content-Length: 38
< Connection: keep-alive
< Server: sowa
< Accept-Ranges: bytes
<
* Connection #0 to host localhost left intact
{"message": "my message", "result": 0}[sowacfg@tkle-ish0038 proxies]$

Отправьте некорректный POST-запрос:

[sowacfg@tkle-ish0038 proxies]$ curl -v --data "{"dat": "data"}" http://localhost:11111/validateMe
* About to connect() to localhost port 11111 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11111 (#0)
> POST /validateMe HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11111
> Accept: */*
> Content-Length: 11
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 11 out of 11 bytes
< HTTP/1.1 403 Forbidden
< Date: Tue, 06 Apr 2021 13:04:17 GMT
< Content-Type: application/octet-stream
< Content-Length: 30
< Connection: keep-alive
< Server: sowa
<
* Connection #0 to host localhost left intact
message: Error in request body[sowacfg@tkle-ish0038 proxies]$

Получен корректный ответ на GET-запрос:

[sowacfg@tkle-ish0038 proxies]$ curl -v http://localhost:11111/validateMe
* About to connect() to localhost port 11111 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11111 (#0)
> GET /validateMe HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11111
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 06 Apr 2021 13:05:33 GMT
< Content-Type: application/json
< Content-Length: 38
< Connection: keep-alive
< Server: sowa
< Accept-Ranges: bytes
<
* Connection #0 to host localhost left intact
{"message": "my message", "result": 0}[sowacfg@tkle-ish0038 proxies]$

Поменяйте в заглушке ответ на некорректный по схеме валидации:

- id: hello_json
  optional:
    response_code: 200
    response_body: "{\"msg\": \"my message\", \"result\": 0}"
  response_headers:
    - name: Content-Type
      value: application/json
  url: ^/validateMe
  listen:
   - port: 10025

Переконфигурируйте и перезапустите профиль заглушек и отправьте запрос:

[sowacfg@tkle-ish0038 proxies]$ curl -v http://localhost:11111/validateMe
* About to connect() to localhost port 11111 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11111 (#0)
> GET /validateMe HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11111
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Date: Tue, 06 Apr 2021 13:09:25 GMT
< Content-Type: text/html
< Content-Length: 52
< Connection: keep-alive
< Server: sowa
<
<html>
<body>
Error in response body
</body>
* Connection #0 to host localhost left intact

Валидация WSDL/XSD#

В предыдущем разделе было рассмотрено, как подключить валидацию на примере JSON. Перейдем к случаю подключения валидации WSDL/XSD.

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

WSDL — это документ XML, описывающий веб-сервис. Он показывает, какие операции доступны и как должны быть структурированы данные для отправки этим операциям. Документы WSDL имеют связанный XSD, в котором показано, что можно поместить в документ WSDL.

Валидация по WSDL#

В данном разделе рассмотрим пример, как можно использовать wsdl схему для валидации веб-сервисов.

В каталоге proxies создайте и наполните соответствующим содержимым файлы dataset.wsdl, dataset.xsd и stringArray.xsd.

dataset.wsdl

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://example.example.com/dataset" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://example.example.com/dataset" name="DataSetProviderImplService">
        <types>
                <xsd:schema>
                        <xsd:import namespace="http://example.example.com/dataset" schemaLocation="dataset.xsd"/>
                </xsd:schema>
                <xsd:schema>
                        <xsd:import namespace="http://jaxb.dev.java.net/array" schemaLocation="stringArray.xsd"/>
                </xsd:schema>
        </types>
        <message name="fetch">
                <part name="sessionKey" type="xsd:int"/>
                <part name="providerName" type="xsd:string"/>
                <part xmlns:ns1="http://jaxb.dev.java.net/array" name="paramNames" type="ns1:stringArray"/>
                <part xmlns:ns2="http://jaxb.dev.java.net/array" name="paramValues" type="ns2:stringArray"/>
                <part xmlns:ns3="http://jaxb.dev.java.net/array" name="fieldNames" type="ns3:stringArray"/>
                <part xmlns:ns4="http://jaxb.dev.java.net/array" name="indexFieldNames" type="ns4:stringArray"/>
                <part xmlns:ns5="http://jaxb.dev.java.net/array" name="indexFieldValues" type="ns5:stringArray"/>
                <part xmlns:ns6="http://jaxb.dev.java.net/array" name="headFields" type="ns6:stringArray"/>
                <part name="rowsCount" type="xsd:long"/>
                <part name="version" type="xsd:long"/>
        </message>
        <message name="fetchResponse">
                <part xmlns:ns7="http://jaxb.dev.java.net/array" name="return" type="ns7:stringArrayArray"/>
                <part xmlns:ns8="http://jaxb.dev.java.net/array" name="headFields" type="ns8:stringArray"/>
                <part name="rowsCount" type="xsd:long"/>
                <part name="version" type="xsd:long"/>
                <part name="finished" type="xsd:boolean"/>
                <part xmlns:ns9="http://jaxb.dev.java.net/array" name="deleted" type="ns9:stringArray"/>
        </message>
        <message name="getDataVersions">
                <part name="sessionKey" type="xsd:int"/>
                <part xmlns:ns10="http://jaxb.dev.java.net/array" name="paramNames" type="ns10:stringArray"/>
        </message>
        <message name="getDataVersionsResponse">
                <part name="return" type="tns:dataVersionArray"/>
        </message>
        <portType name="DataSetProvider">
                <operation name="fetch" parameterOrder="sessionKey providerName paramNames paramValues fieldNames indexFieldNames indexFieldValues headFields rowsCount version finished deleted">
                        <input message="tns:fetch"/>
                        <output message="tns:fetchResponse"/>
                </operation>
                <operation name="getDataVersions" parameterOrder="sessionKey paramNames">
                        <input message="tns:getDataVersions"/>
                        <output message="tns:getDataVersionsResponse"/>
                </operation>
        </portType>
        <binding name="DataSetProviderImplPortBinding" type="tns:DataSetProvider">
                <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
                <operation name="fetch">
                        <soap:operation soapAction=""/>
                        <input>
                                <soap:body use="literal" namespace="http://example.example.com/dataset"/>
                        </input>
                        <output>
                                <soap:body use="literal" namespace="http://example.example.com/dataset"/>
                        </output>
                </operation>
                <operation name="getDataVersions">
                        <soap:operation soapAction=""/>
                        <input>
                                <soap:body use="literal" namespace="http://example.example.com/dataset"/>
                        </input>
                        <output>
                                <soap:body use="literal" namespace="http://example.example.com/dataset"/>
                        </output>
                </operation>
        </binding>
        <service name="DataSetProviderImplService">
                <port name="DataSetProviderImplPort" binding="tns:DataSetProviderImplPortBinding">
                        <soap:address location="http://example:8080/dataset"/>
                </port>
        </service>
</definitions>

dataset.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://example.example.com/dataset" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://example.example.com/dataset">
        <xs:complexType name="dataVersion">
                <xs:sequence>
                        <xs:element name="cleanVersion" type="xs:long" minOccurs="0"/>
                        <xs:element name="filterVersion" type="xs:string" minOccurs="0"/>
                        <xs:element name="newVersion" type="xs:long" minOccurs="0"/>
                        <xs:element name="version" type="xs:long" minOccurs="0"/>
                </xs:sequence>
        </xs:complexType>
 
        <xs:complexType name="dataVersionArray" final="#all">
                <xs:sequence>
                        <xs:element name="item" type="tns:dataVersion" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
                </xs:sequence>
        </xs:complexType>
</xs:schema>

stringArray.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://jaxb.dev.java.net/array" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://jaxb.dev.java.net/array">
        <xs:complexType name="stringArray" final="#all">
                <xs:sequence>
                        <xs:element name="item" type="xs:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
                </xs:sequence>
        </xs:complexType>
 
        <xs:complexType name="stringArrayArray" final="#all">
                <xs:sequence>
                        <xs:element name="item" type="tns:stringArray" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
                </xs:sequence>
        </xs:complexType>
</xs:schema>

Можно заметить, что для примера используется WSDL RPC style. Аналогичные действия по валидации предусмотрены для WSDL DOC style.

Добавьте профиль wsdl_rpc в реестр профилей:

sowa-config --add-profile wsdl_rpc

В каталоге proxies создайте конфигурационный файл wsdl_rpc.yml и наполните его следующим содержимым:

version: 2.0.3
profile: wsdl_rpc
profile_version: XXX
system:
  wrk_count: 4
  conn_count: 4096
  optional:
    log_level: debug
service:
  service_http_proxy:
    - id: service
      listen:
        - port: 8011
      name: service
      hostname:
        - localhost
      url: ^\/service$
      allowed_queries:
        - method: post
      upstream_group_id: upstream_v1
      upstream_groups:
        - id: upstream_v1
          servers:
            - server: 127.0.0.1:18011
              weight: 5
      chains:
        request_chains:
          - message: $clj_request_body
            actions:
              - action: WsdlValidation
                params:
                  validation_schema:
                    type: "file"
                    path: "schemes/xsd/dataset.wsdl"
                conditions:
                  - var: "$request_method"
                    operator: "="
                    val: "POST"
          - message: $clj_response_body
            actions:
              - action: WsdlValidation
                params:
                  validation_schema:
                    type: "file"
                    path: "schemes/xsd/dataset.wsdl"
                conditions:
                  - var: "$request_method"
                    operator: "="
                    val: "POST"
                  - var: "$upstream_status"
                    operator: "!~"
                    val: "(?:500|502|503|504)"

за валидацию по wsdl отвечает действие WsdlValidation.

Параметр валидации - так же validation_schema, условия применения - метод запроса

Для ответов дополнительно задали условия на ожидаемый статус ответа (условие с $upstream_status), в этом случае будет осуществляться валидация ответов только для данных статусов.

В сервисы заглушек добавим заглушку, которая будет возвращать xml ответ (относительно proxies: …/stubs/services/plain_service.yml).

- id: stub_wsdl_rpc
    optional:
      response_body: '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://example.example.com/dataset">
   <soapenv:Header/>
   <soapenv:Body>
      <dat:fetch>
         <sessionKey>3</sessionKey>
         <providerName>sowa hi</providerName>
         <paramNames>
            <item>sowasow sowasow</item>
         </paramNames>
         <paramValues>
            <item>sowa sowas sowaso</item>
         </paramValues>
         <fieldNames>
            <item>sowasowaso sow sowas</item>
         </fieldNames>
         <indexFieldNames>
            <item>sow asowa</item>
         </indexFieldNames>
         <indexFieldValues>
            <item>sowaso sowasowa</item>
         </indexFieldValues>
         <headFields>
            <item>sowasowa so</item>
         </headFields>
         <rowsCount>10</rowsCount>
         <version>10</version>
      </dat:fetch>
   </soapenv:Body>
</soapenv:Envelope>'
      response_code: 200
    response_headers:
      - name: Content-Type
        value: text/html
      - name: Content-Encoding
        value: UTF-8
    listen:
      - port: 18011
    url: ^\/service$

Создайте в ресурсном каталоге профиля wsdl_rpc каталоги schemes и xsd:

mkdir -p /sowa/profile_storage/custom/wsdl_rpc/schemes/xsd

Флаг -p будет создавать вложенные каталоги, но только в случае, если они еще не существуют.

Скопируйте файлы схем в каталог xsd профиля wsdl_rpc:

cp dataset.wsdl /sowa/profile_storage/custom/wsdl_rpc/schemes/xsd
cp dataset.xsd /sowa/profile_storage/custom/wsdl_rpc/schemes/xsd
cp stringArray.xsd /sowa/profile_storage/custom/wsdl_rpc/schemes/xsd

Остановите профиль sample_stub:

sowa-config --stop sample_stub

Переконфигурируйте профиль sample_stub (из каталога proxies):

sowa-config --config ../stubs/sample_stub.yml

Запустите профиль sample_stub:

sowa-config --run sample_stub

Сконфигурируйте профиль wsdl_rpc:

sowa-config --config wsdl_rpc.yml

Запустите профиль wsdl_rpc:

sowa-config --run wsdl_rpc

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

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://example.example.com/dataset">
   <soapenv:Header/>
   <soapenv:Body>
      <dat:getDataVersions>
         <sessionKey>3</sessionKey>
         <paramNames>
            <item>sowa so</item>
         </paramNames>
      </dat:getDataVersions>
   </soapenv:Body>
</soapenv:Envelope>

Отправьте POST запрос c файлом envelope.xml на сервис service, объявленному в конфигурационном файле профиля wsdl_rpc:

curl -v -d @envelope.xml http://127.0.0.1:8011/service

В результате выполнения команды получили в ответ статус код 200. Это означает, что request/response body успешно провалидировались по схеме.

Валидация по XSD#

Для демонстрации работоспособности валидации по XSD будет использована следующую схему: schema.xsd

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Company">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Employee">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:string" name="FirstName"/>
              <xs:element type="xs:string" name="LastName"/>
              <xs:element type="xs:int" name="ContactNo"/>
              <xs:element type="xs:string" name="Email"/>
              <xs:element name="Address">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="City"/>
                    <xs:element type="xs:string" name="State"/>
                    <xs:element type="xs:int" name="Zip"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Добавьте профиль xsd_validation в реестр профилей:

sowa-config --add-profile xsd_validation

В каталоге proxies создайте конфигурационный файл xsd_validation.yml и наполните его следующим содержимым:

version: 2.0.3
profile: xsd_validation
profile_version: XXX
system:
  wrk_count: 4
  conn_count: 4096
  optional:
    log_level: debug
service:
  service_http_proxy:
    - id: service
      listen:
        - port: 8012
      name: service
      hostname:
        - localhost
      url: ^\/service$
      allowed_queries:
        - method: post
      upstream_group_id: upstream_v1
      upstream_groups:
        - id: upstream_v1
          servers:
            - server: 127.0.0.1:18012
              weight: 5
      chains:
        request_chains:
          - message: $clj_request_body
            actions:
              - action: XsdValidation
                params:
                  validation_schema:
                    type: file
                    path: schemes/xsd/schema.xsd
        response_chains:
          - message: $clj_response_body
            actions:
              - action: XsdValidation
                params:
                  validation_schema:
                    type: file
                    path: schemes/xsd/schema.xsd

За валидацию отвечает секция валидаторов — validators, в которой определяется тип валидатора — validator_xsd.

  • validation_schema — обязательный параметр - файл со схемой валидации.

В сервисы заглушек добавим заглушку, которая будет возвращать xml ответ (относительно proxies: …/stubs/services/plain_service.yml).

 - id: stub_xsd_validation
    optional:
      response_body: '<?xml version="1.0" encoding="utf-8"?>
<Company>
  <Employee>
    <FirstName>str1234</FirstName>
    <LastName>str1234</LastName>
    <ContactNo>123</ContactNo>
    <Email>str1234</Email>
    <Address>
      <City>str1234</City>
      <State>str1234</State>
      <Zip>123</Zip>
    </Address>
  </Employee>
</Company>'
      response_code: 200
    response_headers:
      - name: Content-Type
        value: text/html
      - name: Content-Encoding
        value: UTF-8
    listen:
      - port: 18012
    url: ^\/service$

Создайте в ресурсной папке профиля xsd_validation каталоги schemes и xsd:

mkdir -p /sowa/profile_storage/custom/xsd_validation/schemes/xsd

Флаг -p будет создавать вложенные каталоги, но только в случае, если они еще не существуют.

Скопируйте schema.xsd в каталог xsd профиля xsd_validation:

cp schema.xsd /sowa/profile_storage/custom/xsd_validation/schemes/xsd

Сконфигурируйте профиль xsd_validation:

sowa-config -c xsd_validation.yml

Запустите профиль xsd_validation:

sowa-config -r xsd_validation

Переконфигурируйте профиль sample_stub (путь до sample_stub.yml приведен из каталога proxies). Возможен случай, когда профиль не был остановлен ранее. В таком случае конфигуратор выдаст сообщение «Profile sample_stub is running. Are you sure that you want to reconfigure? [y/n]». Нажмите «y».

sowa-config --config ../stubs/sample_stub.yml

Перезапустите профиль sample_stub:

sowa-config --restart sample_stub

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

<?xml version="1.0" encoding="utf-8"?>
<Company>
  <Employee>
    <FirstName>str1234</FirstName>
    <LastName>str1234</LastName>
    <ContactNo>123</ContactNo>
    <Email>str1234</Email>
    <Address>
      <City>str1234</City>
      <State>str1234</State>
      <Zip>123</Zip>
    </Address>
  </Employee>
</Company>

Отправьте POST запрос с файлом envelope2.xml на сервис service, объявленному в конфигурационном файле профиля xsd_validation:

curl -v -d @envelope2.xml http://127.0.0.1:8012/service

В результате выполнения команды был получен в ответ статус код 200. Валидация request/response тела прошла успешно.

Видоизменим файл envelope2.xml, добавив к элементу ContactNo лишние символы — BAD:

<?xml version="1.0" encoding="utf-8"?>
<Company>
  <Employee>
    <FirstName>str1234</FirstName>
    <LastName>str1234</LastName>
    <ContactNoBAD>123</ContactNo>
    <Email>str1234</Email>
    <Address>
      <City>str1234</City>
      <State>str1234</State>
      <Zip>123</Zip>
    </Address>
  </Employee>
</Company>

Повторите POST запрос с файлом envelope2.xml на сервис service, объявленному в конфигурационном файле профиля xsd_validation:

curl -v -d @envelope2.xml http://127.0.0.1:8012/service

В ответе, от профиля xsd_validation, получили статус код 403 Forbidden, что является ошибкой. Для анализа ошибки перейдите в файлы логов профиля xsd_validation. По умолчанию файлы логов хранятся в «/sowalogs/<profile_name>/». В нашем случае «/sowalogs/xsd_validation/».

Нужен каталог services и его подкаталог service_http_proxy. В нем можем найти для каждого объявленного сервиса access и error журналы (<id>_access.log и <id>)_error.log. Откройте service_error.log.

50.png

Посмотрите на «первый» [error], в котором видно, что не удалось найти элемент ContactNoB. Это ошибка валидации связанная с некорректным названием элемента.

Посмотрите вновь к envelope2.xml. Видоизмените его следующим образом — элемент ContactNo имеет тип int. Изменим содержимое данного поля, добавив к числу строку.

<?xml version="1.0" encoding="utf-8"?>
<Company>
  <Employee>
    <FirstName>str1234</FirstName>
    <LastName>str1234</LastName>
    <ContactNo>123BAD</ContactNo>
    <Email>str1234</Email>
    <Address>
      <City>str1234</City>
      <State>str1234</State>
      <Zip>123</Zip>
    </Address>
  </Employee>
</Company>

Повторите POST запрос с файлом envelope2.xml на сервис service, объявленному в конфигурационном файле профиля xsd_validation:

curl -v -d @envelope2.xml http://127.0.0.1:8012/service

В ответе от профиля xsd_validation, была получена ошибка со статус кодом 403 Forbidden. Перейдите к журналу error, чтобы проанализировать ее.

51.png

Здесь видно, что ошибка валидации связана с ограничением схемы на передаваемый тип данных.

Настройка валидации подробно описана в разделе «Валидация по wsdl/xsd схеме».