使用Python Zeep在AnyType中创建具有复杂类型的SOAP消息

r03*_*r03 6 python zeep

我需要创建一个包含以下内容的soap消息:

<saml:Subject>     
    <saml:SubjectConfirmation>      
      <saml:ConfirmationMethod>
               urn:oasis:names:tc:SAML:1.0:cm:holder-of-key
      </saml:ConfirmationMethod>
      <saml:SubjectConfirmationData>
         <saml:Assertion AssertionID="123" 
                         IssueInstant="2018-12-27T17:59:36.284Z" 
                         Issuer="issuer" 
                         MajorVersion="1" 
                         MinorVersion="1">
            ...
         </saml:Assertion>
      </saml:SubjectConfirmationData>
   </saml:SubjectConfirmation>
</saml:Subject>
Run Code Online (Sandbox Code Playgroud)

SubjectConfirmationData是类型的AnyType.
我差不多有这个代码:

assertion_type = client.get_type("saml:AssertionType")
assertion = assertion_type(
    AssertionID = "123",
    MajorVersion = 1,
    MinorVersion = 1,
    Issuer = "issuer",
    IssueInstant = datetime.now())

subject_confirm = {
    'ConfirmationMethod': 'urn:oasis:names:tc:SAML:1.0:cm:holder-of-key',
    'SubjectConfirmationData': assertion
}

result = {
    'Subject': {
        'SubjectConfirmation': subject_confirm
    }
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

<saml:Subject>
  <saml:SubjectConfirmation>
    <saml:ConfirmationMethod>
          urn:oasis:names:tc:SAML:1.0:cm:holder-of-key
    </saml:ConfirmationMethod>
    <saml:SubjectConfirmationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        MajorVersion="1" 
        MinorVersion="1" 
        AssertionID="123" 
        Issuer="issuer" 
        IssueInstant="2018-12-31T13:10:00.471365"
        xsi:type="saml:AssertionType"/>
  </saml:SubjectConfirmation>
</saml:Subject>
Run Code Online (Sandbox Code Playgroud)

问题是AssertionType需要将其包裹在单独的Assertion元素中而不是内部SubjectConfirmationData.如何添加这个额外的元素?

更新1:我也试过这样的东西,但是我收到一个错误:

assertion_elem = client.get_element("saml:Assertion")
assertion = assertion_elem(
    AssertionID = "",
    MajorVersion = 1,
    MinorVersion = 1,
    Issuer = cert_subject,
    IssueInstant = datetime.now())

subj_conf_data_type = client.get_element("saml:SubjectConfirmationData")
subj_conf_data = xsd.AnyObject(assertion_elem, assertion)

subject_confirm = {
    'ConfirmationMethod': 'urn:oasis:names:tc:SAML:1.0:cm:holder-of-key',
    'SubjectConfirmationData': subj_conf_data,
    "KeyInfo": key_info
}
Run Code Online (Sandbox Code Playgroud)

这是错误:

  File "...lib\site-packages\zeep\xsd\types\any.py", line 26, in render
    value.xsd_type.render(parent, value.value, None, render_path)
TypeError: render() takes from 3 to 4 positional arguments but 5 were given
Run Code Online (Sandbox Code Playgroud)

更新2:

我也尝试了这个,但后来我得到了一个奇怪的结果:

assertion_elem = client.get_element("saml:Assertion")
assertion = assertion_elem(
    AssertionID = "",
    MajorVersion = 1,
    MinorVersion = 1,
    Issuer = cert_subject,
    IssueInstant = datetime.now())

subject_confirm = {
    'ConfirmationMethod': 'urn:oasis:names:tc:SAML:1.0:cm:holder-of-key',
    'SubjectConfirmationData': {
        'Assertion': assertion
    },
    "KeyInfo": key_info
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

<saml:Subject>
          <saml:SubjectConfirmation>
            <saml:ConfirmationMethod>
                urn:oasis:names:tc:SAML:1.0:cm:holder-of-key
            </saml:ConfirmationMethod>
            <saml:SubjectConfirmationData>{'Assertion': {
    'Conditions': None,
    'Advice': None,
    '_value_1': {
},
    'Signature': None,
    'MajorVersion': 1,
    'MinorVersion': 1,
    'AssertionID': '123',
    'Issuer': 'issuer',
    'IssueInstant': datetime.datetime(2018, 12, 31, 15, 2, 8, 518253)
}}</saml:SubjectConfirmationData>
          </saml:SubjectConfirmation>
        </saml:Subject>
Run Code Online (Sandbox Code Playgroud)

更新3:

我通过在自定义的zeep插件中创建完整的标头来解决这个问题.
标头使用普通lxml制作,并使用xmlsec签名