जैसा कि आप जानते हैं, उभरते मुद्दों के बारे में डेवलपर्स को सूचित करने के लिए Django बहुत आसान और सरल तंत्र प्रदान करता है। जब प्रोजेक्ट को स्थानीय कंप्यूटर पर तैनात किया जाता है और DEBUG सेटिंग्स ट्रू पर सेट की जाती हैं, तो त्रुटि रिपोर्ट बस HTTP प्रतिक्रिया के रूप में प्रदर्शित होती है, ट्रेसबैक कॉपी करने की क्षमता वाले सुविधाजनक पृष्ठ के रूप में।
यदि यह एक उत्पादन सर्वर है, और DEBUG गलत पर सेट है, तो ADMINS सेटिंग में निर्दिष्ट सभी के लिए डिफ़ॉल्ट रूप से रिपोर्ट ई-मेल से भेजी जाती है (वैसे, यदि आप SMTP सर्वर का उपयोग करते हैं, तो अक्षर नहीं आ सकते हैं, क्योंकि SMTP सर्वर नहीं है रूट को स्वीकार करता है @ स्थानीय होस्ट पता - इस मामले में, बस किसी अन्य पते को निर्दिष्ट करें जिसे आपका एसएमटीपी सर्वर SERVER_EMAIL सेटिंग का उपयोग करके स्वीकार करेगा)।
बेशक, कुछ भी आपको अपने स्वयं के
लॉगिंग हैंडलर (
लॉगिंग हैंडलर ) को लिखने और किसी भी वांछित रूप में त्रुटि रिपोर्ट सहेजने से रोकता है - उदाहरण के लिए, बग ट्रैकर में एक कार्य बनाना।
फिर भी, यदि आपके उपयोगकर्ताओं की सुरक्षा आपके लिए महत्वपूर्ण है, तो एक पूरी तरह से तार्किक सवाल उठता है - उनके लिए त्रुटि रिपोर्ट कैसे सुरक्षित करें? यही है, यह सुनिश्चित करने के लिए कि कोई भी व्यक्तिगत जानकारी उनमें संग्रहीत नहीं है, और किसी को भी मेल द्वारा नहीं भेजा जाता है (आखिरकार, बात यह नहीं है कि डेवलपर्स में से कोई भी बुरा विश्वास कर सकता है, बल्कि यह कि सामान्य रूप से ऐसी जानकारी। सर्वर के बाहर कहीं इसे सहेजना बेहतर नहीं है - आखिरकार, एक मेलबॉक्स को हैक किया जा सकता है, और सर्वर आमतौर पर बेहतर संरक्षित होता है)।
वास्तव में, यह समस्या बहुत आसानी से Django में हल हो गई है, और समाधान लगभग पूरी तरह से आधिकारिक प्रलेखन के हाउ-टू सेक्शन में
वर्णित है।
उदाहरण के लिए, प्राधिकरण के लिए एक सरल दृष्टिकोण अपनाएं:
from django.http import HttpResponse, HttpResponseRedirect from django.core.urlresolvers import reverse from django.contrib.auth import authenticate, login def login_view(request): if request.method != "POST": return HttpResponse("Please use POST.") user = authenticate( email=request.POST.get("email"), password=request.POST.get("password") ) if user is not None: if user.is_active: login(request, user) status = "ok" else: status = "account_disabled" else: status = "invalid_credentials" if status != "ok": return HttpResponse(status) return HttpResponseRedirect(reverse('app.views.index'))
यदि आप स्वयं परीक्षण कर रहे हैं, तो या तो ईमेल को उपयोगकर्ता नाम बदलने के लिए मत भूलना, या ईमेल पते का उपयोग करके लॉग इन करने के लिए एक
प्राधिकरण बैकएंड जोड़ें:
from django.contrib.auth.backends import ModelBackend from django.contrib.admin.models import User class EmailAuthBackend(ModelBackend): def authenticate(self, email=None, password=None, **kwargs): try: user = User.objects.get(email=email) except User.DoesNotExist: return None except User.MultipleObjectsReturned: user = User.objects.filter(email=email)[0] if user.check_password(password): return user return None
अब देखते हैं कि जब कोई त्रुटि होती है तो क्या होता है। व्यवहार में, यहां त्रुटि सबसे अधिक संभावना डेटाबेस की अक्षमता से संबंधित हो सकती है, लेकिन परीक्षण के लिए आप फ़ंक्शन की शुरुआत में केवल एक अपवाद कॉल जोड़ सकते हैं:
raise Exception
अब, यदि कोई लॉग इन करने की कोशिश करता है, तो मेल द्वारा एक रिपोर्ट आती है, विशेष रूप से, अनुरोध के सभी पोस्ट-मापदंडों के बारे में जानकारी:
POST: <QueryDict: {u'csrfmiddlewaretoken ': [u'F3d71EHWECfavaeK4H7nUTzLwgY07AHT'],
u'password ': [u'123'],
u'email ': [u'aruseni.magiku@gmail.com']}>
खैर, यह ईमेल और पासवर्ड है। चलिए अब इस फंक्शन को संवेदनशील_पॉस्टर_पामेटर्स डेकोरेटर में लपेटने की कोशिश करते हैं:
… from django.views.decorators.debug import sensitive_post_parameters @sensitive_post_parameters("password") def login_view(request): …
पासवर्ड खराब नहीं है, अब रिपोर्ट में 20 सितारों को शामिल किया गया है (**********************):
POST: <QueryDict: {u'csrfmiddlewaretoken ': [u'F3d71EHWECfavaeK4H7nUTzLwgY07AHT'],
u'password ': [u' *************************]
u'email ': [u'aruseni.magiku@gmail.com']}>
वैसे, सेंसिटिव_पोस्ट_परमेस्टर डेकोरेटर एक बार में कई तर्क ले सकता है (यह इस बात पर निर्भर करता है कि आप कितने POST पैरामीटर रिपोर्ट में छिपाना चाहते हैं)। या आप तर्कों को छोड़ सकते हैं:
… from django.views.decorators.debug import sensitive_post_parameters @sensitive_post_parameters() def login_view(request): …
इस स्थिति में, त्रुटि रिपोर्ट में सभी POST मापदंडों के मान छिपे हुए हैं:
POST: <QueryDict: {u'csrfmiddlewaretoken ': [u' ********************** ']
u'password ': [u' *************************]
u'email: [यू
लेकिन व्यक्तिगत जानकारी, जिसके प्रकटीकरण को रोका जाना चाहिए, न केवल अनुरोध में पारित POST मापदंडों में शामिल हो सकता है, बल्कि यह भी, उदाहरण के लिए, स्थानीय चर में जो फ़ंक्शन निर्धारित करता है (और जिनके मान त्रुटि रिपोर्ट में शामिल हैं)। उदाहरण के लिए, कल्पना करें कि आपके पास एक फ़ंक्शन प्रोसेस_पेमेंट है, जो विशेष रूप से, डेटाबेस से उपयोगकर्ता के बैंक कार्ड नंबर को प्राप्त करता है और इसे स्थानीय चर भुगतान_कार्ड_आईडी पर लिखता है। जाहिर है, इस चर का मान त्रुटि रिपोर्ट में छिपा होना चाहिए।
यह संवेदनशील_परिवार सज्जाकार का उपयोग करके किया जा सकता है:
… from django.views.decorators.debug import sensitive_variables @sensitive_variables("payment_card_id") def process_payment(request): …
संवेदनशील_पॉस्ट_परैटर्स की तरह, संवेदनशील_विरैबल्स कई तर्कों के उपयोग का समर्थन करता है (अधिक चर छिपाने के लिए), साथ ही साथ बिना किसी तर्कों के उपयोग (सभी स्थानीय फ़ंक्शन चर छिपाने के लिए)।
हालाँकि, कुछ संवेदनशील जानकारी अभी भी शेष है - कुकीज़। जो, विशेष रूप से, एक सत्र पहचानकर्ता होता है (और सत्र पहचानकर्ता का एक संभावित अवरोधन बहुत बुरा होता है)।
COOKIES: {'csrftoken': 'F3d71EHWECfavaeK4H7nUTzLwgY07AHT',
'सेशनिड': '262661787a7f42e787ad18ee853ef8d6'}
खैर, यह थोड़ा अधिक जटिल है, लेकिन महत्वपूर्ण नहीं है।
एप्लिकेशन में डिबग्यूडैम फ़ाइल जोड़ें (यहां इसे "एप्लिकेशन" कहा जाता है, आपके पास कुछ और हो सकता है) और फ़िल्टरिंग क्लास में हमारी स्वयं की त्रुटि रिपोर्टिंग जोड़ें (यह SafeExceptionReporterFilter वर्ग से विरासत में मिलेगा, जिसका उपयोग फ़िल्टरिंग के दौरान किया जाता है संवेदनशील_पॉस्ट_परमीटर्स और संवेदनशील_विरक्षकों को इस्तेमाल किया गया)
from django.views.debug import SafeExceptionReporterFilter from django.http import build_request_repr class CustomExceptionReporterFilter(SafeExceptionReporterFilter): def get_cookies(self, request): if request is None: return {} else: cleansed = request.COOKIES.copy() for key, value in cleansed.iteritems(): cleansed[key] = "secret" return cleansed def get_request_repr(self, request): if request is None: return repr(None) else: return build_request_repr(request, POST_override=self.get_post_parameters(request), COOKIES_override=self.get_cookies(request))
और हम सेटिंग में इंगित करेंगे कि इस विशेष वर्ग को फ़िल्टर करने के लिए उपयोग किया जाना चाहिए:
DEFAULT_EXCEPTION_REPORTER_FILTER = 'app.debug.CustomExceptionReporterFilter'
खैर, अब यह बहुत बेहतर हो गया है:
COOKIES: {'csrftoken': 'secret',
'सेशनिड': 'सीक्रेट',
'टाइमज़ोन': 'गुप्त'}
हालाँकि, कुकी मान अभी भी META शब्दकोश में मौजूद हैं - META ["CSRF_COOKIE"] और META ["HTTP_COOKIE"]। अच्छा, चलो उन्हें वहाँ से हटा दें। :)
from django.views.debug import SafeExceptionReporterFilter from django.http import build_request_repr class CustomExceptionReporterFilter(SafeExceptionReporterFilter): def get_cookies(self, request): if request is None: return {} else: cleansed = request.COOKIES.copy() for key, value in cleansed.iteritems(): cleansed[key] = "secret" return cleansed def get_meta(self, request): if request is None: return {} else: cleansed = request.META.copy() for key in ("HTTP_COOKIE", "CSRF_COOKIE"): cleansed[key] = "secret" return cleansed def get_request_repr(self, request): if request is None: return repr(None) else: return build_request_repr(request, POST_override=self.get_post_parameters(request), COOKIES_override=self.get_cookies(request), META_override=self.get_meta(request))
खैर, अब आपके पास खुशी का अनुभव करते हुए 500 त्रुटि को देखने का एक अनूठा अवसर है - यह महसूस करते हुए कि उपयोगकर्ता अब अधिक सुरक्षित हैं।