2010-02-12 13 views
11

यदि मैं यह सुनिश्चित करना चाहता हूं कि कोई दृश्य सार्वजनिक पहुंच के रूप में सूचीबद्ध है, तो क्या एक सजावटी @public_access के समतुल्य है जो @login_required के विपरीत होगा और यह स्पष्ट करेगा कि दृश्य हमेशा सार्वजनिक रूप से सुलभ होना चाहिए?Django विचारों के लिए @login_required सजावट के विपरीत क्या है?

मुझे लगता है कि एक उपयोग का मामला स्वचालित रूप से कोड में स्पष्ट करने के अलावा सभी सार्वजनिक विचारों में "@csrf_exempt" जोड़ना है कि दृश्य सार्वजनिक रूप से सुलभ होना चाहिए।

उत्तर

10

दुर्भाग्यवश, वर्तमान में Django में इसके लिए कोई अंतर्निहित समर्थन नहीं है, जिससे @login_required को गलती से भूल जाने पर आपको संवेदनशील जानकारी का खुलासा करने का जोखिम मिल जाता है।

middleware/security.py:

def public(function): 
    """Decorator for public views that do not require authentication 
    """ 
    orig_func = function 
    while isinstance(orig_func, partial): # if partial - use original function for authorization 
     orig_func = orig_func.func 
    orig_func.is_public_view = True 

    return function 

def is_public(function): 
    try:         # cache is found 
     return function.is_public_view 
    except AttributeError:     # cache is not found 
     result = function.__module__.startswith('django.') and not function.__module__.startswith('django.views.generic') # Avoid modifying admin and other built-in views 

     try:        # try to recreate cache 
      function.is_public_view = result 
     except AttributeError: 
      pass 

     return result 


class NonpublicMiddleware(object): 

    def process_view_check_logged(self, request, view_func, view_args, view_kwargs): 
     return 

    def process_view(self, request, view_func, view_args, view_kwargs): 
     while isinstance(view_func, partial): # if partial - use original function for authorization 
      view_func = view_func.func 

     request.public = is_public(view_func) 
     if not is_public(view_func): 
      if request.user.is_authenticated():  # only extended checks are needed 
       return self.process_view_check_logged(request, view_func, view_args, view_kwargs) 

      return self.redirect_to_login(request.get_full_path()) # => login page 

    def redirect_to_login(self, original_target, login_url=settings.LOGIN_URL): 
     return HttpResponseRedirect("%s?%s=%s" % (login_url, REDIRECT_FIELD_NAME, urlquote(original_target))) 

settings.py:

MIDDLEWARE_CLASSES = (
    #... 
    'middleware.security.NonpublicProfilefullMiddleware', 
    #... 
) 

, दृश्य कोड और, अंत:

from <projname>.middleware import publi 

@public 
def some_view(request): 
    #... 

# Login required is added automatically 
def some_private_view(request): 
    #... 

यहाँ मेरी परियोजनाओं में से एक से एक समाधान हैइसके अलावा, आप "Automatically decorating all views of a django project" ब्लॉग पोस्ट

+0

मुझे लगता है कि यह भी कुछ मामलों में उपयोगी है * प्रतिबंधित * कुछ कार्यक्षमता अगर एक उपयोगकर्ता के प्रवेश करने के लिए उपयोग। उदाहरण के लिए, एक के लिए अनुमति नहीं देते लॉग इन उपयोगकर्ता पंजीकरण फॉर्म भरने के लिए ... इस मामले में आप संयोजन का उपयोग कर सकते हैं is_authenticated और is_anonymous का है: https://docs.djangoproject.com/en/dev/topics/auth/#authorization-for-anonymous-users – g33kz0r

0

"लॉगिन आवश्यक नहीं है" डिफ़ॉल्ट है। यदि आप यह जानना चाहते हैं कि एक दृश्य कभी भी लॉगिन-प्रतिबंधित नहीं होना चाहिए तो आपको डॉक्टरिंग में ऐसा करना चाहिए।

5

पिछले पोस्टर के रूप में देखना चाहते हैं, लॉगिन आवश्यक नहीं है डिफ़ॉल्ट है।

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

from django.contrib.auth.decorators import user_passes_test 
from django.conf import settings 

LOGGED_IN_HOME = settings.LOGGED_IN_HOME 

def login_forbidden(function=None, redirect_field_name=None, redirect_to=LOGGED_IN_HOME): 
    """ 
    Decorator for views that checks that the user is NOT logged in, redirecting 
    to the homepage if necessary. 
    """ 
    actual_decorator = user_passes_test(
     lambda u: not u.is_authenticated(), 
     login_url=redirect_to, 
     redirect_field_name=redirect_field_name 
    ) 
    if function: 
     return actual_decorator(function) 
    return actual_decorator 
+0

"u.is_anonymous()" का उपयोग "u.is_anonymous()" का उपयोग करें । अधिक जानकारी के लिए https://docs.djangoproject.com/en/dev/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser देखें। – Krozark

1

थोड़ा देर से कर सकता है, लेकिन इस मुद्दे से निपटने के लिए एक और आसान तरीका एक और डेकोरेटर पर भरोसा करते हैं और एक लैम्ब्डा समारोह जोड़ने के लिए होगा:

from django.contrib.auth.decorators import user_passes_test 

@user_passes_test(lambda u: u.is_anonymous) 
+0

क्या बिल्ली है: "संपादन कम से कम 6 अक्षर होना चाहिए; क्या इस पोस्ट में सुधार करने के लिए कुछ और है?" बिलकुल नहीं! 'U.is_anonymous' में केवल गायब ब्रैकेट हैं इसलिए उदाहरण गलत है। – simplylizz

+0

उदाहरण सही है और काम करता है। आप अतिरिक्त ब्रैकेट कहां रखना चाहते थे? –

+0

ओह, मैंने दस्तावेज़ों की जांच की है। आप सही हैं, यह सही है, क्योंकि django 1.10+ 'is_anonymous' एक विशेषता बन गया है। लेकिन Django के पिछले संस्करणों के लिए यह आपको हमेशा 'सत्य' देगा, क्योंकि 'is_anonymous' विधि थी। – simplylizz

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