2

我需要从 Python 访问签名设备。为此,我使用 suds 从位于https://cosigndemo.arx.com:8080/sapiws/dss.asmx?wsdl的 WSDL 生成了一个 Python 客户端。然后,我使用生成的客户端构建了一个简单的签名请求,该请求或多或少与 ARX 提供的 Java 示例中所示的相同(只是,我要求的是不可见的签名)。问题是,当我将请求发送到演示设备时,我收到的回报如下:

(DssSignResult){
   Result = 
      (Result){
         ResultMajor = "urn:oasis:names:tc:dss:1.0:resultmajor:ResponderError"
         ResultMinor = "urn:oasis:names:tc:dss:1.0:resultminor:GeneralError"
         ResultMessage = 
            (ResultMessage){
               value = "Exception occured"
               _lang = "en"
            }
      }
 }

这是我编写的 Python 代码:

from suds.client import Client
from suds.plugin import MessagePlugin
from suds.sax.attribute import Attribute
import logging


class MyPlugin(MessagePlugin):
    def marshalled(self, context):
        foo = context.envelope.getChild('ns2:Body').getChild('ns0:DssSign').getChild('ns0:SignRequest').getChild('ns1:InputDocuments').getChild('ns1:Document')
        foo[0].attributes.append(Attribute('MimeType', 'application/pdf'))
        print context.envelope




url = 'https://cosigndemo.arx.com:8080/sapiws/dss.asmx?wsdl'
client = Client(url, plugins=[MyPlugin()])


cid = client.factory.create("ns4:ClaimedIdentity")
cid.Name = "John Miller"
cid.SupportingInfo.LogonPassword = "12345678"


sigReq = client.factory.create("ns4:RequestBaseType")
sigReq._RequestID = "DummyRequestId"
sigReq.OptionalInputs.ClaimedIdentity = cid
sigReq.OptionalInputs.SignatureType="http://arx.com/SAPIWS/DSS/1.0/signature-field-create-sign"
sigReq.OptionalInputs.SAPISigFieldSettings._Name = "SigField"
sigReq.OptionalInputs.SAPISigFieldSettings._Invisible = "true"
sigReq.OptionalInputs.SAPISigFieldSettings._DependencyMode = "Independent"
sigReq.OptionalInputs.SAPISigFieldSettings._SignatureType = "Digital"
sigReq.OptionalInputs.SAPISigFieldSettings._EmptyFieldLabel = ""
sigReq.OptionalInputs.SAPISigFieldSettings._Page = "1"
sigReq.OptionalInputs.ReturnPDFTailOnly = "true"
sigReq.OptionalInputs.IncludeObject=None
sigReq.OptionalInputs.SignaturePlacement=None


doc = client.factory.create("ns4:DocumentType")


doc.Base64Data = open("/Users/mar/CoSignWSDL/factures-comptat217.pdf", "rb").read().encode("base64")


sigReq.InputDocuments.Document = doc
result = client.service.DssSign(sigReq)
print result

这是(至少我认为)它发送到设备的 SOAP:

<SOAP-ENV:Envelope xmlns:ns3="http://arx.com/SAPIWS/DSS/1.0" xmlns:ns0="http://arx.com/SAPIWS/DSS/1.0/" xmlns:ns1="urn:oasis:names:tc:dss:1.0:core:schema" xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <ns2:Body>
      <ns0:DssSign>
         <ns0:SignRequest RequestID="DummyRequestId">
            <ns1:OptionalInputs>
               <ns1:ClaimedIdentity>
                  <ns1:Name>John Miller</ns1:Name>
                  <ns1:SupportingInfo>
                     <ns3:LogonPassword>12345678</ns3:LogonPassword>
                  </ns1:SupportingInfo>
               </ns1:ClaimedIdentity>
               <ns1:SignatureType>http://arx.com/SAPIWS/DSS/1.0/signature-field-create-sign</ns1:SignatureType>
               <ns1:SAPISigFieldSettings Name="SigField" DependencyMode="Independent" SignatureType="Digital" Page="1" Invisible="true"/>
               <ns1:ReturnPDFTailOnly>true</ns1:ReturnPDFTailOnly>
            </ns1:OptionalInputs>
            <ns1:InputDocuments>
               <ns1:Document>
                  <ns1:Base64Data MimeType="application/pdf">...</ns1:Base64Data>
               </ns1:Document>
            </ns1:InputDocuments>
         </ns0:SignRequest>
      </ns0:DssSign>
   </ns2:Body>
</SOAP-ENV:Envelope>

请注意,出于空间原因,我在这里用“...”替换了(非常长的)Base64Data 内容。为什么它不起作用?

更新由于答案而解决了问题。这是向 PDF 添加 sig 的工作代码:

from suds.client import Client
from suds.plugin import MessagePlugin
from suds.sax.attribute import Attribute
from suds.bindings import binding
import logging
import xml.dom.minidom as minidom
import base64


class MyPlugin(MessagePlugin):
    def marshalled(self, context):
        documentNode = context.envelope.getChild('ns3:Body').getChild('ns0:DssSign').getChild('ns0:SignRequest').getChild('ns1:InputDocuments').getChild('ns1:Document')
        documentNode[0].attributes.append(Attribute('MimeType', 'application/pdf'))
        SAPISigFieldSettingsNode = context.envelope.getChild('ns3:Body').getChild('ns0:DssSign').getChild('ns0:SignRequest').getChild('ns1:OptionalInputs').getChild('ns1:SAPISigFieldSettings')
        SAPISigFieldSettingsNode.setPrefix('ns2')
        ReturnPDFTailOnlyNode = context.envelope.getChild('ns3:Body').getChild('ns0:DssSign').getChild('ns0:SignRequest').getChild('ns1:OptionalInputs').getChild('ns1:ReturnPDFTailOnly')
        ReturnPDFTailOnlyNode.setPrefix('ns2')
        signRequestNode = context.envelope.getChild('ns3:Body').getChild('ns0:DssSign').getChild('ns0:SignRequest')
        signRequestNode.setPrefix('ns1')


binding.envns = ('SOAP-ENV', 'http://www.w3.org/2003/05/soap-envelope')
url = 'https://cosigndemo.arx.com:8080/sapiws/dss.asmx?wsdl'
client = Client(url, plugins=[MyPlugin()])


logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.plugin').setLevel(logging.DEBUG)


cid = client.factory.create("ns4:ClaimedIdentity")
cid.Name = "John Miller"
cid.SupportingInfo.LogonPassword = "12345678"


sigReq = client.factory.create("ns4:RequestBaseType")
sigReq._RequestID = "DummyRequestId"
sigReq.OptionalInputs.ClaimedIdentity = cid
sigReq.OptionalInputs.SignatureType="http://arx.com/SAPIWS/DSS/1.0/signature-field-create-sign"
sigReq.OptionalInputs.SAPISigFieldSettings._Name = "SigField"
sigReq.OptionalInputs.SAPISigFieldSettings._Invisible = "true"
sigReq.OptionalInputs.SAPISigFieldSettings._DependencyMode = "Independent"
sigReq.OptionalInputs.SAPISigFieldSettings._SignatureType = "Digital"
sigReq.OptionalInputs.SAPISigFieldSettings._EmptyFieldLabel = ""
sigReq.OptionalInputs.SAPISigFieldSettings._Page = "1"
sigReq.OptionalInputs.ReturnPDFTailOnly = "true"
sigReq.OptionalInputs.IncludeObject=None
sigReq.OptionalInputs.SignaturePlacement=None


doc = client.factory.create("ns4:DocumentType")
f = open('/Users/mar/CoSignWSDL/factures-comptat217.pdf', 'r+b')
doc.Base64Data = f.read().encode("base64")


sigReq.InputDocuments.Document = doc


result = client.service.DssSign(sigReq)


signature = base64.b64decode(result.SignatureObject.Base64Signature.value)


f.seek(0, 2) #go to the end of the file
f.write(signature)
f.close()
4

1 回答 1

1

您的 SOAP 请求正在传递ns0:SignRequest应该是:ns1:SignRequest

请记住,您的代码中缺少部分——检查设备的 SSL 证书。这不是必须的,但通常需要以验证响应不是由欺诈实体发送的。

在 .Net 和 Java 中,它是在 HTTPS 中访问 Web 服务时自动完成的(基于 Microsoft 证书存储和 Java 证书存储)-但据我所知,Python 中没有等价物。

于 2013-09-15T13:20:39.107 回答