You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中签名SOAP消息并生成WSS安全头?

在Python中为SOAP消息添加WS-Security签名及指定安全头

问题描述

需要为指定SOAP消息生成签名,最终输出必须包含要求的WS-Security安全头。曾尝试使用xmlsectool-3.0.0,但无法添加带有正确命名空间的所需头。

原始SOAP消息

<SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
   <ns1:RequestSecurityTokenCollection>
    <ns1:RequestSecurityToken>
      <wsp:AppliesTo>
        <wsa:EndpointReference>
          <wsa:Address>https://abcd</wsa:Address>
        </wsa:EndpointReference>
      </wsp:AppliesTo>
      <wst:Issuer>
        <wsa:Address>https://xyz</wsa:Address>
      </wst:Issuer>
      <wst:TokenType>urn:ietf:params:oauth:token-type:jwt</wst:TokenType>
      <wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Validate</wst:RequestType>
      <wst:Base>
        <stsuuser:STSUniversalUser xmlns:stsuuser="urn:ibm:names:ITFIM:1.0:stsuuser">
          <stsuuser:Principal>
            <stsuuser:Attribute name="name">
              <stsuuser:Value>john</stsuuser:Value>
            </stsuuser:Attribute>
          </stsuuser:Principal>
          <stsuuser:AttributeList/>
        </stsuuser:STSUniversalUser>
      </wst:Base>
    </ns1:RequestSecurityToken>
   </ns1:RequestSecurityTokenCollection>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

要求的安全头

<SOAP-ENV:Header>
        <wss:Security xmlns:wss="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="NEWID">
                <wsu:Created/>
            </wsu:Timestamp>
            <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="">
                <ds:SignedInfo>
                    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                    <ds:Reference URI="">
                        <ds:Transforms>
                            <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                        </ds:Transforms>
                        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                        <ds:DigestValue>96njoA0fzM8X6G5PWjOp+R4/Gi4=</ds:DigestValue>
                    </ds:Reference>
                    <ds:Reference URI="">
                        <ds:Transforms>
                            <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                        </ds:Transforms>
                        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                        <ds:DigestValue>EXY1Zah4kwz4Dlhc0G3oHIy7HJU=</ds:DigestValue>
                    </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue>Jdkt8TaBmtJGDnsSIdoOibfGAXbqXkKxS4TkQwEfUTWLHyMPe2RqQ1E0ziK1bLU5
CKAcAQ+eRgymP68Zlu3ahW56dTYSBA1DxFFFfD8CtCPikEuQSwMPBWZK5yzlMRm4
ZHv+/XOXYtZRBTT3C+34AAYNn77bE+AAjpcp4VP+xLqv4efTYz/fHVzVkxIh1WpA
tOw0e0WcNrBls1tMe191pAXOJgUXgNChTnGnpr4IVSHinv+HtS54oe0bZwlL3yBp
Gqsq/sIM9pbaTykGW4i6jV9G3vkDiFN2xd/3A45+TQCNu8YXQD9enc96wzVY8LGT
aeYdEXMT9bgNqe1ayqM0NA==</ds:SignatureValue>
            </ds:Signature>
        </wss:Security>
</SOAP-ENV:Header>

解决方案

可以使用Python的zeep库配合xmlsec实现WS-Security签名,具体步骤如下:

1. 安装依赖库

pip install zeep xmlsec

2. 编写签名代码

from zeep.wsse.signature import Signature
from datetime import datetime
from lxml import etree

# 加载原始SOAP消息
soap_content = """
<SOAP-ENV:Envelope xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
  <SOAP-ENV:Body>
   <ns1:RequestSecurityTokenCollection>
    <ns1:RequestSecurityToken>
      <wsp:AppliesTo>
        <wsa:EndpointReference>
          <wsa:Address>https://abcd</wsa:Address>
        </wsa:EndpointReference>
      </wsp:AppliesTo>
      <wst:Issuer>
        <wsa:Address>https://xyz</wsa:Address>
      </wst:Issuer>
      <wst:TokenType>urn:ietf:params:oauth:token-type:jwt</wst:TokenType>
      <wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Validate</wst:RequestType>
      <wst:Base>
        <stsuuser:STSUniversalUser xmlns:stsuuser="urn:ibm:names:ITFIM:1.0:stsuuser">
          <stsuuser:Principal>
            <stsuuser:Attribute name="name">
              <stsuuser:Value>john</stsuuser:Value>
            </stsuuser:Attribute>
          </stsuuser:Principal>
          <stsuuser:AttributeList/>
        </stsuuser:STSUniversalUser>
      </wst:Base>
    </ns1:RequestSecurityToken>
   </ns1:RequestSecurityTokenCollection>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"""

# 转换为lxml元素对象
root = etree.fromstring(soap_content.encode('utf-8'))

# 配置签名参数,替换为你的私钥和证书路径
signature = Signature(
    private_key_file='你的私钥路径.pem',
    certificate_file='你的证书路径.pem',
    signature_method='http://www.w3.org/2000/09/xmldsig#rsa-sha1',
    canonicalization_method='http://www.w3.org/2001/10/xml-exc-c14n#'
)

# 创建符合要求的Timestamp头
timestamp = signature._create_timestamp()
timestamp.set('wsu:Id', 'NEWID')
created_node = timestamp.find('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Created')
created_node.text = datetime.utcnow().isoformat() + 'Z'

# 获取或创建SOAP Header节点
soap_header = root.find('{http://schemas.xmlsoap.org/soap/envelope/}Header')
if soap_header is None:
    soap_header = etree.SubElement(root, '{http://schemas.xmlsoap.org/soap/envelope/}Header')

# 创建Security头并添加Timestamp
security_ns = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
security_node = etree.SubElement(soap_header, '{' + security_ns + '}Security')
security_node.append(timestamp)

# 对Body和Timestamp进行签名
soap_body = root.find('{http://schemas.xmlsoap.org/soap/envelope/}Body')
signature.sign_envelope(root, [soap_body, timestamp])

# 输出签名后的完整SOAP消息
print(etree.tostring(root, pretty_print=True, encoding='utf-8').decode('utf-8'))

关键说明

  • 代码中手动构建了符合要求的Timestamp节点,设置了指定的wsu:Id并填充当前UTC时间
  • 通过zeep的Signature类自动生成符合规范的签名节点,包含指定的算法和引用规则
  • 签名对象同时包含SOAP Body和Timestamp,与需求中的双引用结构匹配
  • 需替换代码中的私钥和证书路径为实际文件路径,确保两者匹配

内容的提问来源于stack exchange,提问作者Redhat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:35:08