Requests: لا يتم إرسال رأس تفويض الجلسة عند إعادة التوجيه

تم إنشاؤها على ٢٨ ديسمبر ٢٠١٥  ·  35تعليقات  ·  مصدر: psf/requests

أنا أستخدم طلبات للوصول إلى developer-api.nest.com وتعيين رأس التفويض برمز حامل. في بعض الطلبات ، تستجيب واجهة برمجة التطبيقات هذه بإعادة توجيه 307. عندما يحدث ذلك ، ما زلت بحاجة إلى إرسال رأس التفويض في الطلب اللاحق. لقد حاولت استخدام requests.get() بالإضافة إلى جلسة.

أفترض أنه يمكنني التغلب على هذا من خلال عدم السماح بعمليات إعادة التوجيه ، واكتشاف 307 ثم إصدار الطلب الجديد بنفسي ، لكني أتساءل عما إذا كان هذا خطأ. هل أتوقع أن يتم إرسال عنوان "التفويض" على جميع الطلبات المقدمة في سياق الجلسة؟

In [41]: s = requests.Session()

In [42]: s.headers
Out[42]: {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'User-Agent': 'python-requests/2.7.0 CPython/3.4.3 Darwin/15.2.0'}

In [43]: s.headers['Authorization'] = "Bearer <snip>"

In [45]: s.get("https://developer-api.nest.com/devices/thermostats/")
Out[45]: <Response [401]>

In [46]: s.get("https://developer-api.nest.com/devices/thermostats/")
Out[46]: <Response [200]>

In [49]: Out[45].history
Out[49]: [<Response [307]>]

In [50]: Out[46].history
Out[50]: []

In [51]: Out[45].request.headers
Out[51]: {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'User-Agent': 'python-requests/2.7.0 CPython/3.4.3 Darwin/15.2.0'}

In [52]: Out[46].request.headers
Out[52]: {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'User-Agent': 'python-requests/2.7.0 CPython/3.4.3 Darwin/15.2.0', 'Authorization': 'Bearer <snip>'}
Bug

التعليق الأكثر فائدة

هناك نوعان من الحلول الخاصة بـ Nest.

الأول هو تمرير المعلمة auth باستخدام access_token بدلاً من استخدام رأس التفويض. لقد وجدت هذا على https://gist.github.com/tylerdave/409ffa08e1d47b1a1e23

الطريقة الأخرى هي حفظ قاموس بالرؤوس التي تستخدمها ، وعدم اتباع عمليات إعادة التوجيه ، ثم تقديم طلب ثانٍ يمر في الرؤوس مرة أخرى:

    headers = {'Authorization': 'Bearer ' + access_token, 'Content-Type': 'application/json'}
    initial_response = requests.get('https://developer-api.nest.com', headers=headers, allow_redirects=False)
    if initial_response.status_code == 307:
        api_response = requests.get(initial_response.headers['Location'], headers=headers, allow_redirects=False)

ال 35 كومينتر

إلى أين يتم إعادة التوجيه؟

آه ، مجال مختلف. firebase-apiserver03-tah01-iad01.dapi.production.nest.com

نعم ، هذا متعمد إلى حد ما: نحن عدوانيون للغاية في تجريد رؤوس التفويض عند إعادة توجيههم إلى مضيف جديد. هذه ميزة أمان للتعامل مع CVE 2014-1829 ، والتي نتجت عن استمرار الرؤوس في عمليات إعادة التوجيه خارج المضيف.

ومع ذلك ، من منظور معين ، لا يزال لدينا خطأ هنا ، لأنك قمت بتعيين رأس التفويض على Session ، وليس الطلب. من حيث المبدأ ، ما يعنيه هذا هو "لا يهمني أين تذهب إعادة التوجيه ، أضف الرأس". ما زلت أعتقد أنني أفضل اتباع هذا النهج ، والذي يضمن على الأقل أننا لسنا منفتحين على أي شكل من أشكال الهجوم ، حتى لو كان هذا المثال المحدد أصعب إلى حد ما. ومع ذلك ، أنا منفتح على الاقتناع بأننا مرتابون للغاية هنا.

ومع ذلك ، أنا منفتح على الاقتناع بأننا مرتابون للغاية هنا.

أنا أقل انفتاحًا على الاقتناع ولكنني على استعداد للاستماع.

ومع ذلك ، يمكن كتابة آلية مصادقة منفصلة لاستمرار مثل هذه الرؤوس عبر النطاقات _ المسموح بها والتي تتطلب منا القيام ببعض الأعمال في rebuild_auth .

لن أجادل في سلامة كيفية عملها الآن. سيكون من الجيد أن يكون لديك آلية ما لاختيار السلوك "غير الآمن" بالرغم من ذلك. ربما يتم تعيين مجال أساسي لاستمرار تلك الرؤوس على (nest.com ، في هذه الحالة) أو ربما قائمة بالمجالات التي يمكن إرسالها إليها.

نعم ، هذا أكثر تعقيدًا بكثير مما سيوفره جوهر الطلبات. لهذا السبب أتساءل عما إذا كانت فئة / معالج مصدق منفصل قد يعمل بشكل أفضل لهذا النوع من الأشياء. لست مقتنعًا بأنه سيعمل على الرغم من أنني متأكد تمامًا من أننا لا ندعو prepare_auth بدون قيد أو شرط.

لن يعمل في النموذج القياسي لأننا لا ندعو prepare_auth دون قيد أو شرط. ومع ذلك ، يمكن استخدام محول النقل لأداء هذا الدور ، حتى لو كان استخدامًا غير عادي إلى حد ما لواجهة برمجة التطبيقات هذه.

أعتقد أن TA هو الشيء الخطأ تمامًا الذي يجب التوصية به هنا.

  • إذا تم توفير المصادقة لجلسة ما ، فيجب إرسالها لكل طلب تقدمه هذه الجلسة.
  • ربما يتعين علينا إزالة session.auth . إنها ليست مفيدة بشكل خاص.

إذا تم توفير المصادقة لجلسة ما ، فيجب إرسالها لكل طلب تقدمه هذه الجلسة.

أنا لا أوافق بشكل أساسي. لا تُستخدم الجلسات لمجال واحد ، إذا كانت كذلك ، فلن أواجه مشكلة في ذلك.

ربما يجب علينا إزالة session.auth. إنها ليست مفيدة بشكل خاص.

أعتقد أنه مفيد. أعتقد أنه سيكون من الأفضل إذا لم يُسمح بتعيين tuple لها. أفضل رؤية فئة المصادقة التي تحدد المجالات التي يجب استخدامها من أجلها. يمكننا فقط اعتماد AuthHandler من حزام أدوات الطلبات الذي يسمح للأشخاص بتحديد بيانات اعتماد لمجال عند استخدام الطلبات. يوفر هذا طريقة أكثر أمانًا قليلاً للتعامل مع المصادقة المستندة إلى الجلسة. الجانب السلبي هو أنه يتطلب من المستخدمين الاشتراك في هذا النوع من المصادقة.

أحتاج أيضًا إلى إصلاح هذا حتى يمكنني جعل الرؤوس مستمرة لعمليات إعادة التوجيه.

jtherrmann إذا كان هذا هو رأس المصادقة ، فإن أسهل طريقة لحل المشكلة هي تعيين معالج مصادقة على مستوى الجلسة يضع دائمًا الرأس الذي تريده على الطلب.

هل تم إعطاء أي تقدم أو اعتبار إضافي لذلك؟
أنا على التوالي في نفس القضية.

ethanroy لا يوجد أي اعتبار إضافي يتجاوز اقتراحي باستخدام معالج مصادقة على مستوى الجلسة ، في التعليق الموجود أعلى تعليقك مباشرةً.

ذات صلة: إذا أعادت الجلسة توجيه المصادقة وشرائطها ، فإن استدعاء get مرة أخرى يعيد تطبيق المصادقة ويستخدم إعادة التوجيه المخزنة مؤقتًا. لذا اطرق مرتين وتدخل. سلوك مقصود؟

>>> s = requests.Session()
>>> s.headers.update({"Authorization": "Token {}".format(API_TOKEN)})
>>> s.get(url)

<Response [403]>

>>> s.get(url)

<Response [200]>

GregBakker نعم ، إيش. إنه التقاء السلوكيات المقصودة. ومع ذلك ، يشير هذا الخطأ إلى أنه لا ينبغي أن يحدث الخطأ 403 الأصلي.

Lukasa عندما تقول "إن أسهل طريقة للتغلب على المشكلة هي تعيين معالج مصادقة على مستوى الجلسة" ، فهل هذا شيء يعمل اليوم؟ بناءً على ما أراه في الكود ، فإن الإجابة هي لا ، لكن صياغتك تجعلني أتساءل عما إذا كنت أفقد شيئًا. أنت تتحدث عن تعيين سمة مصادقة الجلسة ، أليس كذلك؟

نعم ، هذا _يجب_ العمل.

jwineinger إذن كيف انتهى بك الأمر إلى الالتفاف على هذه المشكلة؟ لا يزال يبدو أنه يتصرف بنفس الطريقة.

هناك نوعان من الحلول الخاصة بـ Nest.

الأول هو تمرير المعلمة auth باستخدام access_token بدلاً من استخدام رأس التفويض. لقد وجدت هذا على https://gist.github.com/tylerdave/409ffa08e1d47b1a1e23

الطريقة الأخرى هي حفظ قاموس بالرؤوس التي تستخدمها ، وعدم اتباع عمليات إعادة التوجيه ، ثم تقديم طلب ثانٍ يمر في الرؤوس مرة أخرى:

    headers = {'Authorization': 'Bearer ' + access_token, 'Content-Type': 'application/json'}
    initial_response = requests.get('https://developer-api.nest.com', headers=headers, allow_redirects=False)
    if initial_response.status_code == 307:
        api_response = requests.get(initial_response.headers['Location'], headers=headers, allow_redirects=False)

لقد واجهت هذه المشكلة نفسها وتجاوزتها من خلال تجاوز طريقة rebuild_auth في تنفيذ requests.Session مخصص:

from requests import Session

class CustomSession(Session):
    def rebuild_auth(self, prepared_request, response):
        return

s = CustomSession()
s.get(url, auth=("username", "password"))

@ sigmavirus24 ما الخطأ في حل @ gabriel-loo؟ مخاوف أمنية؟

@ j08lue نعم. يرجى قراءة الموضوع. هناك عناصر CVE مرتبطة بعدم تجريد المصادقة قبل اتباع عمليات إعادة التوجيه العشوائية إلى مجال جديد. فكر في المشكلة بهذه الطريقة:

أقوم بتقديم طلبات إلى api.github.com وتمكن أحد المهاجمين من إجباري على اتباع إعادة توجيه إلى another-domain.com يتحكمون فيه وأقوم بتمرير الرمز المميز الخاص بي مع حق الوصول للكتابة إلى مستودعاتي (بما في ذلك الطلبات) ثم يمكن أن يظهر كما لو أنني أقوم بالتزامات للطلبات بينما هم في الواقع يقومون بهذه الالتزامات عبر واجهة برمجة التطبيقات. يمكن أن تتضمن تعليمات برمجية في الطلبات من شأنها إضعاف وضعها الأمني ​​وربما تضر بك بشكل فعال. هذا ما يمكن أن يحدث عندما ترسل بيانات اعتماد المصادقة الخاصة بك دون قيد أو شرط في كل عملية إعادة توجيه.

ومع ذلك ، لنفترض أن إعادة التوجيه ليست ضارة ، هل أنت مرتاح حقًا لتسريب بيانات الاعتماد الخاصة بك لخدمة إلى شركة أو خدمة أخرى؟ قد تخزن الخدمة الأصلية بيانات سرية لك أو لعملائك أو لأي شيء آخر. حتى إذا كان المجال الجديد الذي تمت إعادة توجيهك إليه لا يستخدم بيانات الاعتماد الخاصة بك ولكن يُحتمل أن يسجلها على أنها بيانات غير متوقعة ، يمكن للشخص الذي يهاجمها ويمكنه استرداد هذه السجلات استخدام بيانات الاعتماد الخاصة بك مقابل النطاق الأصلي إذا كان بإمكانه معرفة مكان هم ينتمون. هل أنت حقًا على استعداد لتحمل هذا الخطر؟

شكرًا على الرسم التوضيحي ، @ sigmavirus24. إذا كان هذا القلق يحظر في النهاية إعادة توجيه الرؤوس الحساسة إلى عمليات إعادة التوجيه ، فلماذا لا يزال هذا الموضوع مفتوحًا؟ لم أستطع التفكير في خطأ أكثر ملاءمة من الخطأ الذي حصلت عليه (403) ، لذلك لا داعي لاتخاذ إجراء هنا ، أليس كذلك؟ أو ما الذي يدور

كنت أواجه هذه المشكلة مؤخرًا عند العمل باستخدام واجهة برمجة تطبيقات غير عامة. تعتبر المخاوف الأمنية منطقية تمامًا كسبب لتجريد المصادقة من عمليات إعادة التوجيه. أعتقد أن حلًا مثل @ gabriel-loo هو شيء يمكن للأشخاص التفكير فيه إذا كانوا يعتقدون أنهم في بيئة آمنة بما يكفي للقيام بذلك. أو معالج مستوى الجلسة. أو ابحث عن طريقة أخرى للتغلب على هذه المشكلة عن طريق تخطي إعادة التوجيه تمامًا كما هو مقترح أعلاه ، إذا كان ذلك ممكنًا. تماشيًا مع وجهة النظر ، هذا ليس خطأ حقًا.

ومع ذلك ، فقد قضيت وقتًا أطول مما كنت بحاجة إليه على الأرجح للارتباك حول سبب قيام عدد قليل من عملاء HTTP غير Python _did_ بتمرير رأس المصادقة وعملوا بشكل جيد عندما لم يكن الأمر كذلك. اقتراح واحد: قد يكون من الجيد إصدار تحذير عبر warnings هنا لتوضيح الأمر أكثر للمتصلين عندما يكون العنوان موجودًا ويتم تجريده. أتصور أنه من النادر أن يكون هذا شيئًا لا يريد المتصل أن يتم تحذيره بشأنه.

tlantz عادة يبدو ذلك معقولًا جدًا. تسببت الطلبات كمشروع (بالإضافة إلى urllib3 ، أحد تبعياته) في قدر كبير من الغضب عندما يصدر أي نوع من التحذير سواء عبر وحدة التحذيرات أو عبر التسجيل. علاوة على ذلك ، فإن وحدة التحذيرات مخصصة للأشياء التي يجب على الأشخاص اتخاذ إجراء بشأنها ، على سبيل المثال ، عدم استخدام إصدار من Python تم تجميعه مقابل إصدار حديث من OpenSSL.

في معظم الحالات ، لا يمثل هذا السلوك مشكلة مثل عدم القدرة على التحقق من شهادة لاتصال TLS ، على سبيل المثال. من الواضح أن هذا لا يساعدك أو يساعدك أي شخص آخر عبر عن إحباطه الحقيقي والصحيح بشأن هذه المسألة. مع أخذ ذلك في الاعتبار ، أتساءل عما إذا كان من الأفضل محاولة تسجيل هذا على المستوى DEBUG . إذا كان شخص ما يستخدم التسجيل (ممارسة لائقة بشكل عام) ويمكّن هذا المستوى من الظهور له. علاوة على ذلك ، نظرًا لقلة سجلات الطلبات نفسها ، سيكون هذا بارزًا إلى حد ما كسجل تصحيح. هل هذا يبدو وكأنه مقايضة عادلة؟

نعم ، هذا يبدو وكأنه مقايضة عادلة تمامًا. التفكير حول warnings أمر منطقي بالنسبة لي. أعتقد أنه بحلول الوقت الذي شعرت فيه بالحيرة لمدة 30 دقيقة أو أنك عادة ما تضيف logging حول أغراضك الخاصة على أي حال عند DEBUG ، لذلك أعتقد أن رسالة DEBUG سيصيب 95٪ من الحالات التي يكون فيها الناس عالقين في محاولة اكتشاف ما لا يعمل.

أستخدم جلسة لعقد رأس التفويض ، ولكن لا يتم إرسالها في إعادة توجيه
الطلبات (2.18.4)

قضيت أنا وزميل في العمل ما لا يقل عن ساعتين في تصحيح مشكلة تتعلق مباشرة بهذا السلوك. حالة الاستخدام الخاصة بي هي إعادة توجيه استدعاء واجهة برمجة التطبيقات من api.my-example-site.org إلى www.api.my-example-site.org . تم تجريد الرؤوس في إعادة التوجيه.

إذا كان هذا هو السلوك المقصود (أو إذا لم يتم تغييره في المستقبل القريب) ، فهل يمكننا على الأقل إضافته إلى الوثائق؟ قرأت وأعدت قراءة المستندات محاولًا اكتشاف ما كنت أفعله بشكل غير صحيح ، حتى أنني قرأت كل التعليمات البرمجية في فئة Request . إذا رأيت تحذيرًا بشأن هذا السلوك في الوثائق ، كنت سأصلح مشكلتي في غضون دقيقتين (وهو الوقت الذي استغرقته بعد أن وجدت سلسلة الرسائل هذه). ربما كنا نقرأ في الجزء الخطأ من التوثيق.

مرحبًا ndmeiri ، لدينا دعوة بخصوص هذا في دليل البدء السريع رؤوس مخصصة . إذا كنت تشعر أن هناك مكانًا أفضل لوضع هذا ، يسعدنا مراجعة أي اقتراحات لديك. أفضل أن ننقل ذلك إلى قضية منفصلة أو العلاقات العامة على الرغم من أنه لا يرتبط مباشرة بهذه التذكرة. شكر!

مرحبًا nateprewitt ، شكرًا للإشارة إلى قسم الرؤوس المخصصة! من الواضح أنني لم أفكر في التحقق من هذا الجزء من الوثائق.

أعتقد أنه سيكون من المفيد أيضًا تضمين المكالمة أو الإشارة إلى المكالمة في القسم الخاص بالمصادقة . على الرغم من أنني مشغول حاليًا إلى حد ما ، إلا أنني سأفكر في فتح العلاقات العامة عندما تهدأ الأمور لتحديث المستندات.

إذا كان هذا هو السلوك المقصود

ndmeiri نعم ، إنه سلوك مقصود هو عدم تسريب بيانات اعتماد المصادقة الحساسة إلى مصادر يحتمل أن تكون غير موثوق بها. (فقط لأكون واضحا)

يبدو أن "المجالات الموثوقة" من 4983 # لم تعد في تنفيذ Session.py.

في الحالة التي أقوم فيها بتقديم طلبات إلى عنوان URL الذي _ أعرفه_ يعيد توجيهه إلى عنوان URL مختلف ولكنه آمن ، وأريد تمكين إعادة التوجيه مع استمرار رأس التفويض ، كيف يمكنني تحقيق ذلك من فضلك؟

كيف يمكنني تحقيق ذلك من فضلك؟

يمكنك تصحيح طريقة rebuild_auth . يعمل هذا بالنسبة لي: https://github.com/DHI-GRAS/earthdata-download/blob/master/earthdata_download/download.py#L27 -L49

@ j08lue شكرا! قبل أن يأتي تعليقك ، عملت على حل المشكلة عن طريق تعيين allow_redirects إلى False ، وإضافة رمز لمتابعة عمليات إعادة التوجيه القليلة المحددة المتوقعة في حالة الاستخدام الخاصة بي. هذا موقف قصير المدى بالنسبة لي ، لذلك آمل أن يكون هذا حلًا مؤقتًا مناسبًا ، لكن من الرائع معرفة أن هناك طريقة أفضل للقيام بذلك على المدى الطويل إذا لزم الأمر.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

NoahCardoza picture NoahCardoza  ·  4تعليقات

mitar picture mitar  ·  4تعليقات

xsren picture xsren  ·  3تعليقات

cnicodeme picture cnicodeme  ·  3تعليقات

justlurking picture justlurking  ·  3تعليقات