Python, 기본 인증을 사용하는 HTTPS GET


89

파이썬을 사용하여 기본 인증으로 HTTPS GET을 시도하고 있습니다. 나는 파이썬을 처음 접했고 가이드는 다른 라이브러리를 사용하여 일을하는 것 같습니다. (http.client, httplib 및 urllib). 누구든지 그 방법을 보여줄 수 있습니까? 표준 라이브러리에 사용을 어떻게 알릴 수 있습니까?


2
인증서가 유효한지 확인 하시겠습니까?
Andrew Cox

1
stackoverflow.com/questions/635113/…을 확인하십시오 . 당신이 찾고있는 것을 정확히 커버하는 것 같습니다.
Geo

답변:


120

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 2014

22
대신 변수를 사용하려면 다음을 사용 b"username:password"하십시오 bytes(username + ':' + password, "utf-8")..
kenorb

1
@ jgomo3 : -> 변환 .decode("ascii")전용입니다 . 결과는 어쨌든 ASCII 전용입니다. bytesstrb64encode
Torsten Bronger 2010 년

1
나의 구원자. 4 시간의 고군분투와 잘못된 방향 전환 후.
Conrad B

기본 자격 증명을 어떻게 사용합니까?, 다른 시스템에서 코드를 올바르게 실행하면 작동하지 않습니까?
anandhu

91

Python의 힘을 사용하고 최고의 라이브러리 중 하나 인 요청 에 의지하십시오.

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")

아래는 Python 2.6에서 작동합니다.

pycurl하루에 천만 건 이상의 요청을 처리하는 프로세스를 위해 프로덕션에서 많이 사용 합니다.

먼저 다음을 가져와야합니다.

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()

다양한 컬 옵션을 설정할 수 있습니다. 전체 옵션 목록 은이를 참조하십시오 . 링크 된 문서는 libcurl API 용이지만 다른 언어 바인딩에 대한 옵션은 변경되지 않습니다.

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)

인증서를 확인할 필요가없는 경우. 경고 : 이것은 안전하지 않습니다. running 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 패키지는 파이썬 3에서 사용할 수 없습니까?
Ocaj Nires 2011 년

httplib2로 업데이트되었습니다. 이것은 파이썬 3에서 사용할 수 있습니다.
Ocaj Nires 2011 년

새로운 사용자를 위해 : 위의 예에는 점이 없습니다. "pycurl.HTTPHEADER"(편집하지만 1 자이고 최소값은 6입니다).
Graeme Wicksted 2014

영업 이익은 GET, POST되지 말했다
조 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)이 안전한지 확인해야합니다.
four43

정확 해 보이지만 제 경우에는 작동하지 않았습니다. ssl.SSLCertVerificationError : [SSL : CERTIFICATE_VERIFY_FAILED]와 같은 오류가 발생합니다. 인증서 확인 실패 : 로컬 발급자 인증서 (_ssl.c : 1056)를 가져올 수 없음
neelmeg

유효한 pem 인증서를 verify 매개 변수 및 쿠키 매개 변수에 전달하여 알았습니다.
neelmeg 19

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대신 function 을 사용하는 경우 인코딩을 설정해야합니다 b"".


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

토큰이있는 경우 비밀번호는 ''.

그것은 나를 위해 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.