0

I am currently writing a python language plugin for a compiler I have written that automates http calls for a RESTful API. I have managed to get the login/authentication working using the socket and ssl modules, but this low-level approach seems to create potential problems with parsing the response in order to obtain the authentication token and secret. The requests module seems popular/efficient, however, I cannot seem to get it to function properly for my particular authentication needs. I am using a trust store in the form of a .pem file (containing just a public key) that I converted from my .jks file used to authenticate for the Java plugin. The server expects the username and password to be submitted in the request body in json format. Here is the code I have been trying to use:

#Server and login data
...
host = 'localhost'
port = 8443
pem_file = "C:\\Users\\aharasta\\pycert.pem"

#Digest password with MD5 algorithm
m = hashlib.md5()
m.update(password)
encrypted_password = m.hexdigest()

url = <url>
data = {'userid': user_name, 'password': encrypted_password}
json_data = json.dumps(data)
headers = {'Content-type': 'application/json', 'Accept': 'text/plain', 'Content \                     
          Length': len(json_data)} 

r = requests.post(url, headers = headers, data = json_data, cert = pem_file)
print(r)

Upon execution, this code will raise an SSL error stating "certificate verify failed". If I add the parameter verify = False or verify = pem_file, I will receive a 404 response from the server. I should also note that when I launch the server in debug mode and execute the request (with one of the verify parameters), it never makes it to the server's authentication methods, or any methods for that matter. Any insight or help on this matter would be greatly appreciated!

4

1 回答 1

1

首先,您发布的内容有几个问题:

  • 您指定但未给出示例host,因此我们可以猜测您正在使用本地部署进行测试,并且可以实际查看对服务器的请求。我不确定您在谈论什么方法,但是如果您使用类似于 Flask 的东西进行服务器开发,您可能不想将身份验证作为 JSON 编码数据发送。有 Authentication 标头是有原因的,请求有 Authentication 处理程序是有原因的。;-)porturl

  • 您不应该Content-Length自己指定标题。requests 将为您执行此操作。除此之外,您指定它不正确(根据您发布的内容),因此 404 可能来自接收您的服务器无法识别的标头。

现在,应该没有理由指定verify=False,您可以指定cert=pem_fileverify=pem_file。一个或两个都可以,但你永远不应该使用verify=False.

最后,SSLError引发的 是告诉您pem您提供的文件与服务器指定的文件不匹配。考虑到这一点,您可能需要检查本地服务器的设置。Requests 本身不处理证书验证,但 urllib3 提供了它。我们只是根据您提供的参数进行设置。我怀疑这是 urllib3 的错,因为它引发了SSLError标准库ssl模块产生的问题。

编辑

说明在文档中指定的*.pem文件cert无效。您必须使用verify='/path/to/file.pem'才能正确执行此操作。

编辑#2

要检查已发送的请求,您可以执行以下操作:

r = requests.post(...)
r.request
# PreparedRequest('POST', url, ...)
r.request.body
r.request.headers
# etc.

要在发送前修改请求,您可以执行以下操作:

from requests import Request, Session

s = Session()
r = Request('POST', url, datajson_data, headers=headers)
p = r.prepare()
p.body = 'New body'
p.headers = #etc.
s.send(p, verify=pem_file)
于 2013-02-05T15:51:24.100 回答