Python istekleri: POST isteği bırakma Yetkilendirme başlığı


9

Python istekleri kitaplığını kullanarak bir API POST isteği yapmaya çalışıyorum. Bir Authorizationbaşlıktan geçiyorum ama hata ayıklamayı denediğimde, başlığın bırakıldığını görebiliyorum. Ne olup bittiği hakkında bir fikrim yok.

İşte benim kod:

access_token = get_access_token()
bearer_token = base64.b64encode(bytes("'Bearer {}'".format(access_token)), 'utf-8')
headers = {'Content-Type': 'application/json', 'Authorization': bearer_token}
data = '{"FirstName" : "Jane", "LastName" : "Smith"}'
response = requests.post('https://myserver.com/endpoint', headers=headers, data=data)

Yukarıda da görüldüğü gibi, ben manuel olarak ayarlanan Authorizationistek argümanlar içinde kafayla ancak asıl isteğin başlıklarını eksik: {'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.4.3 CPython/2.7.9 Linux/4.1.19-v7+'}.

Ek bir bilgi, POST isteğini bir GET isteğine değiştirirsem, Authorizationbaşlığın normal şekilde geçmesi!

Neden bu kütüphane POST istekleri için başlığı bırakıyor ve bunu nasıl çalıştırabilirim?

Lib ve Python 2.7.9 isteklerinin v2.4.3 sürümünü kullanma

Yanıtlar:


10

TLDR

İstediğiniz url, POST isteklerini farklı bir ana bilgisayara yönlendirir, böylece istek kitaplığı Authoriztion, kimlik bilgilerinizi sızdırmaktan korkar. Bunu düzeltmek için isteklerin Sessionsınıfında sorumlu yöntemi geçersiz kılabilirsiniz .

ayrıntılar

2.4.3 isteklerinde reqeuests, Authorizationbaşlığı kaldırdığı tek yer , bir isteğin farklı bir ana bilgisayara yeniden yönlendirilmesidir. Bu ilgili kod :

if 'Authorization' in headers:
    # If we get redirected to a new host, we should strip out any
    # authentication headers.
    original_parsed = urlparse(response.request.url)
    redirect_parsed = urlparse(url)

    if (original_parsed.hostname != redirect_parsed.hostname):
        del headers['Authorization']

Yeni sürümlerinde requests, Authorizationbaşlık ek durumlarda kaldırılacaktır (örneğin, yönlendirme güvenli olandan güvenli olmayan bir protokole ise).

Muhtemelen sizin durumunuzda olan, POST isteklerinizin farklı bir ana bilgisayara yönlendirilmesidir. İstek kitaplığını kullanarak yeniden yönlendirilmiş bir ana makine için kimlik doğrulaması sağlamanın tek yolu bir .netrcdosyadır. Ne yazık ki bu sadece size yardımcı olmayan HTTP Temel Kimlik Doğrulaması'nı kullanmanıza izin verecektir. Bu durumda, en iyi çözüm muhtemelen şu şekilde alt sınıfı sınıflandırmak requests.Sessionve geçersiz kılmaktır :

from requests import Session

class NoRebuildAuthSession(Session):
    def rebuild_auth(self, prepared_request, response):
        """
        No code here means requests will always preserve the Authorization
        header when redirected.
        Be careful not to leak your credentials to untrusted hosts!
        """

session = NoRebuildAuthSession()
response = session.post('https://myserver.com/endpoint', headers=headers, data=data)

Düzenle

Bu durumda bir uyarı eklemek için github istek kitaplığına bir çekme isteği açtım . İkinci bir onayın birleştirilmesini bekliyor (üç ay zaten).


1
Teşekkürler, sorun buydu!
user4184113

0

İstek belgelerinin söyledikleri:

Authorization headers set with headers= will be overridden if credentials are specified in .netrc, which in turn will be overridden by the auth= parameter. Authorization headers will be removed if you get redirected off-host.

İsteğinize yönlendiriliyor musunuz?

Bu durumda, posta isteğinde yönlendirmeyi bu seçenekle devre dışı bırakmayı deneyin:

allow_redirects=False


allow_redirects=Falseisteklerin sunucu tarafından istenen yeniden yönlendirmeyi izlemesini engeller. Bu, isteği tamamlamaya yardımcı olmaz, sadece ortasında durur.
kmaork

0

Gördüğüm ilk (ve belki de gerçek) sorun, nasıl oluşturduğunuzdur, bearer_tokençünkü yalnızca simgenizi değil aynı zamanda kimlik doğrulama türünü de kodluyorsunuz'Bearer'

Anladığım kadarıyla sadece jetonu kodlamanız ve boş kimlik doğrulama türünü + istek başlığınızdaki kodlanmış jetonu sağlamanız gerekir:

bearer_token = str(base64.b64encode(access_token.encode()), "utf8")
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer {}'.format(bearer_token)}

(Ayrıca) bir yönlendirme sorunu ise, doğru yeri bulabilir ve bu url'ye isteğinizi iletebilir veya POSTsunucu bunu kabul ederse, erişim kodunu gövdenin içinde göndermeyi düşünebilirsiniz .


0

Belgelerden: Requests will attempt to get the authentication credentials for the URL’s hostname from the user’s netrc file. The netrc file overrides raw HTTP authentication headers set with headers=. If credentials for the hostname are found, the request is sent with HTTP Basic Auth.

Yeniden yönlendiriliyorsanız, kullanmayı deneyebilirsiniz allow_redirects=false


-1

başlıklarda özel bir yetkilendirme kullanmayı deneyebilirsiniz.

Özel bir kimlik doğrulama sınıfı tanımlayın:

class MyAuth(requests.auth.AuthBase):
def __init__(self, bearer_token):
    self.username = None
    self.bearer_token = bearer_token

def __call__(self, r):
    r.headers['Authorization'] = self.bearer_token
    return r

ardından isteği göndermek için bunu kullanın:

headers = {'Content-Type': 'application/json'}

data = '{"FirstName" : "Jane", "LastName" : "Smith"}'

response = requests.post('https://myserver.com/endpoint', headers=headers, auth=MyAuth(bearer_token), data=data)

Bu işe yararsa lütfen cevabı kabul edin. Veya hâlâ sorun yaşıyorsanız bize bildirin. Bu yardımcı olur umarım.


Devralmaya gerek yok requests.auth.AuthBase. Bunun için kaynak koduna bakarsanız, NotImplementedgeçersiz kılmayı unutursanız , tüm yaptığı şeyin arttığını görürsünüz __call__.
Monica

Bu, soruda açıklanan davranışı değiştirmez. Yetkilendirmeyi bir yönlendirme üzerinde yeniden oluştururken, istekler yetkilendirme argümanını kullanmaz.
kmaork
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.