2010-07-12 11 views
42

मैं वर्तमान उपयोगकर्ता को स्टोर करने और वस्तुओं का अनुरोध करने के लिए थ्रेड स्थानीय का उपयोग कर रहा हूं। इस तरह से मैं प्रोग्राम में कहीं से भी अनुरोध (जैसे गतिशील रूपों) के पास उन्हें पास करने के बिना आसानी से पहुंच प्राप्त कर सकता हूं।Django खराब में थ्रेड स्थानीय का उपयोग क्यों कर रहा है?

एक मिडलवेयर में धागा स्थानीय लोगों भंडारण को लागू करने के लिए, मैं Django साइट पर एक ट्यूटोरियल का पालन किया: लेख से http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser?version=20

: http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser?version=18

इस दस्तावेज़ के बाद से इस तकनीक से परहेज सुझाव देने के लिए संशोधित किया गया है :

एक डिजाइन बिंदु से, थ्रेडलोकल्स अनिवार्य रूप से वैश्विक चर हैं, और पोर्टेबिलिटी और predictabi की सभी सामान्य समस्याओं के अधीन हैं यह दर्शाता है कि वैश्विक चर आमतौर पर लागू होते हैं।

अधिक महत्वपूर्ण बात यह है कि सुरक्षा बिंदु से, थ्रेडलोकल्स एक बड़ा जोखिम पैदा करते हैं। एक डेटा स्टोर प्रदान करके जो अन्य धागे की स्थिति का खुलासा करता है, आप अपने वेब सर्वर में एक थ्रेड के लिए सिस्टम में किसी अन्य थ्रेड की स्थिति को संभावित रूप से संशोधित करने का एक तरीका प्रदान करते हैं। यदि थ्रेडलोकल डेटा में उपयोगकर्ताओं या अन्य प्रमाणीकरण से संबंधित डेटा के विवरण शामिल हैं, तो उस डेटा को किसी ऐसे हमले के आधार के रूप में उपयोग किया जा सकता है जो किसी अनधिकृत उपयोगकर्ता तक पहुंच प्रदान करता है, या किसी उपयोगकर्ता के निजी विवरण का खुलासा करता है। हालांकि इस तरह के हमले से सुरक्षित एक थ्रेडलोकल प्रणाली बनाना संभव है, रक्षात्मक होने के लिए यह बहुत आसान है और ऐसी प्रणाली का निर्माण करना जो पहले ऐसी किसी भी भेद्यता के अधीन नहीं है।

मुझे समझ में आता है कि वैश्विक चर खराब क्यों हो सकते हैं, लेकिन इस मामले में मैं अपने स्वयं के सर्वर पर अपना कोड चला रहा हूं, इसलिए मुझे नहीं पता कि दो वैश्विक चर किस खतरे में हैं।

क्या कोई शामिल सुरक्षा समस्या को समझा सकता है? मैंने कई लोगों से पूछा है कि अगर वे इस लेख को पढ़ते हैं और जानते हैं कि मैं थ्रेड स्थानीय लोगों का उपयोग कर रहा हूं, तो वे मेरे आवेदन को हैक कर सकते हैं, फिर भी कोई मुझे बताने में सक्षम नहीं है। मुझे संदेह करना शुरू हो रहा है कि यह बाल-विभाजन वाले शुद्धवादियों द्वारा आयोजित एक राय है जो वस्तुओं को स्पष्ट रूप से पारित करना पसंद करते हैं।

+2

वैसे - आप मूल उदाहरण है? अब यह नष्ट कर दिया है और मुझे लगता है कि उपयोग करना चाहते हैं ... – rslite

+2

यह टुकड़ा सुंदर हटाए गए पृष्ठ के समान है: http://djangosnippets.org/snippets/2179/ – hekevintran

+0

GlobalRequest मिडलवेयर: https://djangosnippets.org/snippets/2853 –

उत्तर

39

मैं पूरी तरह से असहमत हूं। टीएलएस बेहद उपयोगी है। इसका ध्यान देखभाल के साथ किया जाना चाहिए, जैसे कि ग्लोबल्स को देखभाल के साथ इस्तेमाल किया जाना चाहिए; लेकिन कह रहे हैं कि इसका उपयोग बिल्कुल नहीं किया जाना चाहिए जैसा कि हास्यास्पद है क्योंकि ग्लोबल्स का कभी भी उपयोग नहीं किया जाना चाहिए।

उदाहरण के लिए, मैं वर्तमान में टीएलएस में सक्रिय अनुरोध संग्रहीत करता हूं। इससे यह मेरे लॉगिंग क्लास से सुलभ हो जाता है, बिना किसी इंटरफ़ेस के माध्यम से अनुरोध पास किए बिना - जिनमें से कई जो Django के बारे में परवाह नहीं करते हैं। यह मुझे कोड में कहीं से भी लॉग प्रविष्टियां करने देता है; लॉगर डेटाबेस तालिका में आउटपुट करता है, और यदि कोई लॉग बनने पर कोई अनुरोध सक्रिय होता है, तो यह सक्रिय उपयोगकर्ता की तरह चीजों को लॉग करता है और अनुरोध किया जा रहा था।

यदि आप नहीं चाहते हैं कि एक थ्रेड में किसी अन्य थ्रेड के टीएलएस डेटा को संशोधित करने की क्षमता हो, तो अपने टीएलएस को इसे प्रतिबंधित करने के लिए सेट करें, जिसे शायद मूल टीएलएस कक्षा का उपयोग करने की आवश्यकता है।मुझे उस तर्क को समझ में नहीं आता है, यद्यपि; यदि कोई हमलावर मनमाने ढंग से पाइथन कोड को आपके बैकएंड के रूप में निष्पादित कर सकता है, तो आपका सिस्टम पहले से ही मोटे तौर पर समझौता कर चुका है - उदाहरण के लिए, वह बाद में किसी अन्य उपयोगकर्ता के रूप में चलाने के लिए बंदर पैच कुछ भी कर सकता है।

जाहिर है, आप एक अनुरोध के अंत में किसी भी टीएलएस स्पष्ट करने के लिए चाहता हूँ; Django में, इसका मतलब है कि इसे प्रक्रिया_response और process_exception में मिडलवेयर क्लास में साफ़ करना।

+0

आपकी पुष्टि के लिए धन्यवाद। अब मैं कम पागल महसूस करता हूँ =)। यदि कोई हमलावर थ्रेडलोकल डेटा पढ़ सकता है, तो वह मेरी मशीन में एसएसएच को वैसे भी सक्षम होना चाहिए। – hekevintran

+2

आवश्यक नहीं एसएसएच, लेकिन कम से कम पाइथन बैकएंड पर कुछ प्रकार का नियंत्रण रखना है। पूरी बहस बहुत अच्छी तरह से प्रतीत होती है, वैसे भी। –

+1

मैं उत्सुक हूं कि, वास्तव में, आपका मतलब है "अनुरोध के अंत में किसी भी टीएलएस को साफ़ करें"। इसे कैसे साफ़ करें? 'लोकल 'ऑब्जेक्ट को ही हटा रहा है, या सिर्फ' स्थानीय 'ऑब्जेक्ट पर विशेषता जिसमें आपने सत्र संग्रहीत किया था? हालांकि, ईमानदार होने के लिए, मुझे यह भी यकीन नहीं है कि उनके बीच कोई प्रासंगिक अंतर है या नहीं। – CoreDumpError

10

इस तथ्य के बावजूद कि आप विभिन्न उपयोगकर्ताओं से डेटा मिला सकते हैं, थ्रेड स्थानीय लोगों से बचा जाना चाहिए क्योंकि वे निर्भरता को छुपाते हैं। यदि आप किसी विधि को तर्क देते हैं जो आप देखते हैं और जानते हैं कि आप क्या गुजर रहे हैं। लेकिन एक धागा स्थानीय पृष्ठभूमि में एक छिपे हुए चैनल की तरह कुछ है और आप सोच सकते हैं कि कुछ मामलों में एक विधि सही तरीके से काम नहीं करती है।

कुछ ऐसे मामले हैं जहां थ्रेड स्थानीय एक अच्छी पसंद हैं, लेकिन इनका उपयोग शायद ही कभी और सावधानी से किया जाना चाहिए!

+4

लेकिन यह कोई समस्या नहीं है क्योंकि मुझे पता है कि कहीं भी थ्रेड लोकल का उपयोग किया जाता है, मैं get_current_user() को कॉल करता हूं। वैसे भी धागे स्थानीय में केवल दो चर हैं। – hekevintran

9

कैसे एक टीएलएस मिडलवेयर के साथ संगत बनाने के लिए पर एक त्वरित उदाहरण नवीनतम Django 1.10:

# coding: utf-8 
# Copyright (c) Alexandre Syenchuk (alexpirine), 2016 

try: 
    from threading import local 
except ImportError: 
    from django.utils._threading_local import local 

_thread_locals = local() 

def get_current_request(): 
    return getattr(_thread_locals, 'request', None) 

def get_current_user(): 
    request = get_current_request() 
    if request: 
     return getattr(request, 'user', None) 

class ThreadLocalMiddleware(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     _thread_locals.request = request 
     return self.get_response(request) 
+1

यह UWSGI का उपयोग करते समय काम नहीं करता है। 'स्थानीय()' साझा किया गया है –

+0

क्या आप आगे बता सकते हैं, @ जेवियरबुज़ी? क्या आपका मतलब है कि UWSGI का उपयोग करते समय 'स्थानीय()' धागे में साझा किया जाता है? क्या आपके पास स्पष्टीकरण है कि वह क्यों है? – alexpirine

+0

जिस तरह से यूडब्ल्यूएसजीआई काम करता है, यह चीजों को गति देने के लिए सभी धागे के बीच सबकुछ साझा करता है। https://www.pythonanywhere.com/forums/topic/710/ - यह परीक्षण करने में काफी आसान है: पीआईपी यूवीजीआईआई स्थापित करें और इसे अपने लिए जांचें - एक साइड नोट के रूप में, मुझे एक मिडलवेयर बनाना था जो कैश बनाता है अनुरोध की शुरुआत और अनुरोध के अंत में इसे साफ़ करें .. बस सुनिश्चित करने के लिए - अन्यथा मुझे uwsgi –

संबंधित मुद्दे