2017-11-10 20 views
0

受信ホストが自己署名証明書を使用しています(これは変更される予定ではありません)ので、明らかな証明書の検証は無視する必要があります私が受け取ったエラー。SSL証明書の検証なしでurllibを使用してデータを投稿する

私の最初のスクリプトは、このように見えた:

from urllib.request import Request, urlopen 
from urllib.parse import urlencode 

post_url = "https://myserver.mydomain.com:30005/myapipath" 
post_payload = { "event": { "Title": "Something, sometime, something, Python"} } 
post_headers = {'Content-Type': 'application/xml'} 

omi_post = Request(url=post_url, data=post_payload, headers=post_headers) 

urlopen(omi_post) 

と述べたように、これは以下のスタックトレースを生成:

Traceback (most recent call last): File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 1318, in do_open encode_chunked=req.has_header('Transfer-encoding')) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1239, in request self._send_request(method, url, body, headers, encode_chunked) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1285, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1234, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1026, in _send_output self.send(msg) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 964, in send self.connect() File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1400, in connect server_hostname=server_hostname) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", line 407, in wrap_socket _context=self, _session=session) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", line 814, in init self.do_handshake() File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", line 1068, in do_handshake self._sslobj.do_handshake() File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", line 689, in do_handshake self._sslobj.do_handshake() ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "send_data.py", line 16, in urlopen(post_it_already) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 223, in urlopen return opener.open(url, data, timeout) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 526, in open response = self._open(req, data) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 544, in _open '_open', req) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 504, in _call_chain result = func(*args) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 1361, in https_open context=self._context, check_hostname=self._check_hostname) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 1320, in do_open raise URLError(err) urllib.error.URLError:

をだから私は、SSLコンテキストに追加することについて話しました別のポストを見つけました私は次のようにしました:

from urllib.request import Request, urlopen 
from urllib.parse import urlencode 
import ssl 

ctx = ssl.create_default_context() 
ctx.check_hostname = False 
ctx.verify_mode = ssl.CERT_NONE 

post_url = "https://myserver.mydomain.com:30005/myapipath" 
post_payload = { "event": { "Title": "Something, sometime, something, Python"} } 
post_headers = {'Content-Type': 'application/xml'} 

post_it_already = Request(url=post_url, data=post_payload, headers=post_headers) 

urlopen(post_it_already, context=ctx) 

しかし、これは次のスタックトラを生成しますCE(私はそれで私の拳を振るどんなに):

Traceback (most recent call last): File "send_data.py", line 15, in urlopen(post_it_already, context=ctx) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 223, in urlopen return opener.open(url, data, timeout) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 526, in open response = self._open(req, data) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 544, in _open '_open', req) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 504, in _call_chain result = func(*args) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 1361, in https_open context=self._context, check_hostname=self._check_hostname) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", line 1318, in do_open encode_chunked=req.has_header('Transfer-encoding')) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1239, in request self._send_request(method, url, body, headers, encode_chunked) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1285, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1234, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1064, in _send_output + b'\r\n' TypeError: can't concat str to bytes

私はそれがバイトのオブジェクトと文字列を連結文句だ理由として途方に暮れてよ。私はそれが私の文字列型URLと私のデータ型のペイロードとヘッダーが好きではないと仮定しますか?しかし、私は次に何をすべきか分からない。

これは、別の2つのサンプルコードを取って、ピーナッツとバブルガムのように実際に一緒に作業することを期待する古典的なケースですか?

答えて

0

post_payloadは、 'str'ではなく 'bytes'タイプである必要があります。 Python docsから

class urllib.request.Request ...

...

For an HTTP POST request method, data should be a buffer in the standard application/x-www-form-urlencoded format. The urllib.parse.urlencode() function takes a mapping or sequence of 2-tuples and returns an ASCII string in this format. It should be encoded to bytes before being used as the data parameter.

...

あなたはthis Python urllib howtoで説明するよう.encode()方法を使用してバイトにpost_payloadを変換することができます。

これはSSL検証の問題とは別ですが、POSTデータを送信しようとしたために、HTTPS接続が正常に確立されたと考えられます。

+0

ありがとうございました。私は盲目的に他のコードスニペットから自分のコードを構築する共通のトラップに落ちました。私は最初にドキュメントを読む必要があります。 URLエンコードには.parseを使用し、リンクしたドキュメントと同じように.encodeを使用してバイトに変換しました。 – irwazr

0

@ contextlib.contextmanagerデコレータとrequestsモジュールを代わりに使用できます。それははるかに簡単なアプローチです。

以下のコード

は何上記のコードはありませんが、それは「 verify=False」でrequests.Session.requestのための部分的な方法を生成し、「 Unverified Https request」と言う警告をフィルタである

@contextlib.contextmanager 
def no_ssl_verification(): 
    old_request = requests.Session.request 
    requests.Session.request = partialmethod(old_request,verify=False) 

    warnings.filterwarnings('ignore', 'Unverified HTTPS request') 
    yield 

    warnings.resetwarnings() 
    requests.Session.request = old_request 

だけで正常に動作します。

with no_ssl_verification: 
    request = requests.post( 
          url, 
          json={ 
            'name' : some_name 
           },auth(username,password) 
          ) 

より良い解決策が見つかった場合は、私にお知らせください。

関連する問題