问题
Background
I'm building a SOAP client with python 2.7.3 and using the suds 0.4.1 library provided by Canonical. The server is using basic authentication over HTTPS.
Problem
Can't pass authentication on the server, even to get at the WSDL. I get the following error:
suds.transport.TransportError: HTTP Error 401: Unauthorized
Attempts at resolution and code
I have tried both of the authentication methods described in the suds documentation, but still get the error above at the client = Client(url, ...)
line. I've confirmed the credentials and ability to connect in a web browser, which works fine.
After declaring wsdl_url
, username
and password
, I tried:
client = Client(url=wsdl_url, username=username, password=password)
# as well as:
t = HttpAuthenticated(username=username, password=password)
client = Client(url=wsdl_url, transport=t)
# and even:
t = HttpAuthenticated(username=username, password=password)
t.handler = urllib2.HTTPBasicAuthHandler(t.pm)
t.urlopener = urllib2.build_opener(t.handler)
client = Client(url=wsdl_url, transport=t)
That last one seems to, at least, get a response from the WSDL URL in another question about HTTP authentication with suds.
Other notes
This question is distinct from this similar question because I am using:
from suds.transport.https import HttpAuthenticated
# not:
# from suds.transport.http import HttpAuthenticated
and from the Traceback, the client = Client(url, ...)
call clearly hits suds.transport.https.py:
File "/usr/lib/python2.7/dist-packages/suds/client.py", line 112, in __init__ self.wsdl = reader.open(url)
File "/usr/lib/python2.7/dist-packages/suds/reader.py", line 152, in open d = self.fn(url, self.options)
File "/usr/lib/python2.7/dist-packages/suds/wsdl.py", line 136, in __init__ d = reader.open(url)
File "/usr/lib/python2.7/dist-packages/suds/reader.py", line 79, in open d = self.download(url)
File "/usr/lib/python2.7/dist-packages/suds/reader.py", line 95, in download fp = self.options.transport.open(Request(url))
File "/usr/lib/python2.7/dist-packages/suds/transport/https.py", line 60, in open return HttpTransport.open(self, request)
File "/usr/lib/python2.7/dist-packages/suds/transport/http.py", line 64, in open raise TransportError(str(e), e.code, e.fp)
What am I missing?
回答1:
suds wasn't adding the authorization header to the request, so I set it manually:
import base64
# code excluded for brevity
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
authenticationHeader = {
"SOAPAction" : "ActionName",
"Authorization" : "Basic %s" % base64string
}
client = Client(url=wsdl_url, headers=authenticationHeader)
回答2:
You can used SOAPpy
import SOAPpy, base64
class myHTTPTransport(SOAPpy.HTTPTransport):
username = None
passwd = None
@classmethod
def setAuthentication(cls,u,p):
cls.username = u
cls.passwd = p
def call(self, addr, data, namespace, soapaction=None, encoding=None, http_proxy=None, config=SOAPpy.Config, timeout=None):
if not isinstance(addr, SOAPpy.SOAPAddress):
addr = SOAPpy.SOAPAddress(addr, config)
if self.username != None:
addr.user = self.username+":"+self.passwd
return SOAPpy.HTTPTransport.call(self, addr, data, namespace, soapaction, encoding, http_proxy, config)
if __name__ == '__main__':
# code for authenticating the SOAP API calls
myHTTPTransport.setAuthentication('admin', 'admin')
# Getting the instance of Server
Baton = SOAPpy.WSDL.Proxy(<WSDL PATH>, transport=myHTTPTransport)
# your code goes here
...
来源:https://stackoverflow.com/questions/11742494/python-soap-client-wsdl-call-with-suds-gives-transport-error-401-unauthorized-f