Python、基本認証を使用したHTTPS GET


90

Pythonを使用して基本認証でHTTPSGETを実行しようとしています。私はPythonに非常に慣れていないので、ガイドはさまざまなライブラリを使用して作業を行っているようです。(http.client、httplibおよびurllib)。誰かがそれがどのように行われたかを私に見せてもらえますか?標準ライブラリに使用するように指示するにはどうすればよいですか?


2
証明書が有効であることを確認しますか?
アンドリューコックス

1
stackoverflow.com/questions/635113/…をチェックしてください。それはあなたが探しているものを正確にカバーしているようです。
geo

回答:


122

Python 3では、以下が機能します。標準ライブラリの下位レベルのhttp.clientを使用しています。基本認証の詳細については、rfc2617のセクション2も確認してください。このコードは、証明書が有効であることを確認しませんが、https接続をセットアップします。これを行う方法については、http.clientのドキュメントを参照してください。

from http.client import HTTPSConnection
from base64 import b64encode
#This sets up the https connection
c = HTTPSConnection("www.google.com")
#we need to base 64 encode it 
#and then decode it to acsii as python 3 stores it as a byte string
userAndPass = b64encode(b"username:password").decode("ascii")
headers = { 'Authorization' : 'Basic %s' %  userAndPass }
#then connect
c.request('GET', '/', headers=headers)
#get the response back
res = c.getresponse()
# at this point you could check the status etc
# this gets the page text
data = res.read()  

5
request方法のマニュアル[1] ISO-8859-1「HTTPのデフォルトの文字セット『』文字列として符号化される」と述べています。したがって、「ASCII」ではなく「ISO-8859-1」でデコードすることをお勧めします。[1] docs.python.org/3/library/...
jgomo3

22
の代わりに変数を使用するにはb"username:password"、次を使用しますbytes(username + ':' + password, "utf-8")
kenorb 2015年

1
@ jgomo3:これ.decode("ascii")bytes->str変換専用です。b64encodeとにかく、の結果はASCIIのみです。
Torsten Bronger 2016年

1
わたしの救世主。4時間の苦労と大量の方向転換の後。
コンラッド

デフォルトの資格情報を使用するにはどうすればよいですか?別のシステムでコードを実行すると、これは機能しませんか?
anandhu

93

Pythonの力を利用して、周りの最高のライブラリの1つに頼りましょう:リクエスト

import requests

r = requests.get('https://my.website.com/rest/path', auth=('myusername', 'mybasicpass'))
print(r.text)

変数r(応答の要求)には、使用できるパラメーターがたくさんあります。最良のことは、インタラクティブインタプリタに飛び込んでそれをいじったり、リクエストドキュメントを読んだりすることです。

ubuntu@hostname:/home/ubuntu$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> r = requests.get('https://my.website.com/rest/path', auth=('myusername', 'mybasicpass'))
>>> dir(r)
['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'iter_content', 'iter_lines', 'json', 'links', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']
>>> r.content
b'{"battery_status":0,"margin_status":0,"timestamp_status":null,"req_status":0}'
>>> r.text
'{"battery_status":0,"margin_status":0,"timestamp_status":null,"req_status":0}'
>>> r.status_code
200
>>> r.headers
CaseInsensitiveDict({'x-powered-by': 'Express', 'content-length': '77', 'date': 'Fri, 20 May 2016 02:06:18 GMT', 'server': 'nginx/1.6.3', 'connection': 'keep-alive', 'content-type': 'application/json; charset=utf-8'})

23

更新:OPはPython 3を使用しているため、httplib2を使用して例を追加します

import httplib2

h = httplib2.Http(".cache")

h.add_credentials('name', 'password') # Basic authentication

resp, content = h.request("https://host/path/to/resource", "POST", body="foobar")

以下はPython2.6で機能します。

私はpycurl、1日あたり1,000万件以上のリクエストを処理するプロセスの本番環境で多くを使用しています。

最初に以下をインポートする必要があります。

import pycurl
import cStringIO
import base64

基本認証ヘッダーの一部は、Base64としてエンコードされたユーザー名とパスワードで構成されています。

headers = { 'Authorization' : 'Basic %s' % base64.b64encode("username:password") }

HTTPヘッダーに、この行が表示されますAuthorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=。エンコードされる文字列は、ユーザー名とパスワードによって異なります。

ここで、HTTP応答を書き込む場所とcurl接続ハンドルが必要です。

response = cStringIO.StringIO()
conn = pycurl.Curl()

さまざまなカールオプションを設定できます。オプションの完全なリストについては、これを参照してください。リンクされたドキュメントはlibcurlAPI用ですが、他の言語バインディングのオプションは変更されません。

conn.setopt(pycurl.VERBOSE, 1)
conn.setopt(pycurlHTTPHEADER, ["%s: %s" % t for t in headers.items()])

conn.setopt(pycurl.URL, "https://host/path/to/resource")
conn.setopt(pycurl.POST, 1)

証明書を確認する必要がない場合。警告:これは安全ではありません。実行中curl -kまたはに似ていcurl --insecureます。

conn.setopt(pycurl.SSL_VERIFYPEER, False)
conn.setopt(pycurl.SSL_VERIFYHOST, False)

cStringIO.writeHTTP応答を保存するための呼び出し。

conn.setopt(pycurl.WRITEFUNCTION, response.write)

POSTリクエストを行うとき。

post_body = "foobar"
conn.setopt(pycurl.POSTFIELDS, post_body)

今すぐ実際のリクエストを行ってください。

conn.perform()

HTTP応答コードに基づいて何かを実行します。

http_code = conn.getinfo(pycurl.HTTP_CODE)
if http_code is 200:
   print response.getvalue()

これは、3を使用したpyhthon 2.5 imの場合のようです
Tom Squires

簡単なインストールまたはpipを使用していますか?pycurlパッケージはPython3では利用できませんか?
Ocaj Nires 2011

httplib2で更新されました。これは
Python3で

新規の方へ:上記の例にはドットがありません: "pycurl.HTTPHEADER"(編集しますが、1文字で最小は6です)。
Graeme Wicksted 2014

OPはPOSTではなくGETと言った
Joe C

17

証明書の検証を使用してPython3で基本認証を行う正しい方法はurllib.request次のとおりです。

これcertifiは必須ではないことに注意してください。OSバンドル(おそらく* nixのみ)を使用するか、MozillaのCAバンドルを自分で配布することができます。または、通信するホストが少数の場合は、ホストのCAから自分でCAファイルを連結します。これにより、別の破損したCAによって引き起こされるMitM攻撃のリスクを減らすことができます。

#!/usr/bin/env python3


import urllib.request
import ssl

import certifi


context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(certifi.where())
httpsHandler = urllib.request.HTTPSHandler(context = context)

manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
manager.add_password(None, 'https://domain.com/', 'username', 'password')
authHandler = urllib.request.HTTPBasicAuthHandler(manager)

opener = urllib.request.build_opener(httpsHandler, authHandler)

# Used globally for all urllib.request requests.
# If it doesn't fit your design, use opener directly.
urllib.request.install_opener(opener)

response = urllib.request.urlopen('https://domain.com/some/path')
print(response.read())

これは素晴らしい。プレーンテキストの資格情報(HTTP基本認証)を送信する場合、証明書の検証は重要です。TLSレイヤー(HTTPS)が安全であることを確認する必要があります。これは、そのレイヤーが安全であることに依存しているためです。
four 4318年

ルックスは修正しますが、私の場合は仕事をしませんでした、それはssl.SSLCertVerificationErrorのようなエラーがスローされます。[SSLを:CERTIFICATE_VERIFY_FAILED]証明書が失敗したことを確認しますローカル発行者証明書を取得できません(_ssl.c:1056)
neelmeg

有効なpem証明書をverifyparamとcookiesparamに渡すことでそれを理解しました。
neelmeg

1

標準モジュールのみを使用し、手動ヘッダーエンコーディングは使用しません

...これは意図された最もポータブルな方法のようです

python urllibの概念は、リクエストの多数の属性をさまざまなマネージャー/ディレクター/コンテキストにグループ化することです...次に、それらの部分を処理します。

import urllib.request, ssl

# to avoid verifying ssl certificates
httpsHa = urllib.request.HTTPSHandler(context= ssl._create_unverified_context())

# setting up realm+urls+user-password auth
# (top_level_url may be sequence, also the complete url, realm None is default)
top_level_url = 'https://ip:port_or_domain'
# of the std managers, this can send user+passwd in one go,
# not after HTTP req->401 sequence
password_mgr = urllib.request.HTTPPasswordMgrWithPriorAuth()
password_mgr.add_password(None, top_level_url, "user", "password", is_authenticated=True)

handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
# create OpenerDirector
opener = urllib.request.build_opener(handler, httpsHa)

url = top_level_url + '/some_url?some_query...'
response = opener.open(url)

print(response.read())

0

@AndrewCoxの回答に基づいて、いくつかのマイナーな改善を加えました。

from http.client import HTTPSConnection
from base64 import b64encode


client = HTTPSConnection("www.google.com")
user = "user_name"
password = "password"
headers = {
    "Authorization": "Basic {}".format(
        b64encode(bytes(f"{user}:{password}", "utf-8")).decode("ascii")
    )
}
client.request('GET', '/', headers=headers)
res = client.getresponse()
data = res.read()

bytes代わりに関数を使用する場合は、エンコーディングを設定する必要があることに注意してくださいb""


-1
requests.get(url, auth=requests.auth.HTTPBasicAuth(username=token, password=''))

トークンを使用する場合、パスワードは''

わたしにはできる。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.