检查django中每个请求的授权

时间:2015-06-11 20:13:45

标签: python django

我有一个Django应用程序设置如下:

MyApp
    CustomAdmin
        urls
        models
        views
    MainApp
        settings
        urls
        wsgi
    SomeOtherApp
        admin
        models
        views

现在,在我的MainApp.urls中,我设置了以下网址:

url(r'^api/admin/', include('CustomAdmin.urls')),

CustomAdmin中,我希望有一种机制来检查请求是否由superuser创建,而不管相关视图如何。如果它是由超级用户创建的,则该请求应由关联的视图函数处理,否则它应该抛出403或类似的错误。

我在Laravel中使用了类似的东西,如下所示

Route::group(
    array(
        'before' => 'auth.admin',
        'prefix' => 'api/admin'        
        ),
    function(){
        ....
    });

我不确定Django中是否存在这样的机制。如果有,我该怎么办?

3 个答案:

答案 0 :(得分:3)

您可以编写middleware,以便在视图中处理请求之前对请求进行一些处理。在名为middleware.py的文件中,输入:

from django.contrib.auth.views import redirect_to_login

class AllowSuperUserOnly(object):
    def process_request(self, request):
        if request.path.startswith('/api/admin/'):
            if not request.user.is_superuser:
                return redirect_to_login(request.path)
        # Continue processing the request as usual:
        return None

将中间件添加到settings.py。它看起来应该类似于:

MIDDLEWARE_CLASSES = (
    ...
    'your_app.middleware.AllowSuperUserOnly',
)

答案 1 :(得分:1)

我认为不可能在包含其他人的url模式上定义它(稍后会对此进行更多测试),但至少可以CustomAdmin.urls使用user_passes_test装饰者。

# CustomAdmin/urls.py
from django.contrib.auth.decorators import user_passes_test
from CustomAdmin import views

requires_superuser = user_passes_test(lambda x: x.is_superuser)

urlpatterns = patterns(
    '',
    url(  # with a class based view
        r'^$', 
        requires_superuser(views.SomeView.as_view()), 
        name='someview'
    ),
    url(  # with a functional view
        r'^(?P<foo>\w+)/$', 
        requires_superuser(views.someotherview),    
        name='someotherview'
    ),
)

答案 2 :(得分:0)

ccbv.co.ukDjango Class-bases views docsdispatch()是在基于类的视图中调用的第一个方法。

查看课程工作流程

  1. 调度()
  2. http_method_not_allowed()
  3. 选项()
  4. 请记住,所有通用视图都会继承View类

    中间件是一个很好的解决方案,但如果您不需要预先处理每个请求,您可以使用访问mixin

    正如我之前所说,dispatch()是第一个执行的方法,因此您可以重新编写它以授予或拒绝访问视图。

    以下是dispatch默认代码:

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
    

    你可以写一个mixin课程:

    class SuperuserRequiredMixin(object):
        """
        Mixin allows you to require a user with `is_superuser` set to True.
        """
    
        login_url = settings.LOGIN_URL  # LOGIN_URL from project settings
        raise_exception = False  # Default whether to raise an exception to none
        redirect_field_name = REDIRECT_FIELD_NAME  # Set by django.contrib.auth
    
        def dispatch(self, request, *args, **kwargs):
            if not request.user.is_superuser:  # If the user is a standard user,
                if self.raise_exception:  # *and* if an exception was desired
                    return HttpResponseForbidden()  # return a forbidden response.
                else:
                    # otherwise, redirect the user to the login page.
                    # Also, handily, sets the `next` GET argument for
                    # future redirects.
                    path = urlquote(request.get_full_path())
                    tup = self.login_url, self.redirect_field_name, path
                    return HttpResponseRedirect("%s?%s=%s" % tup)
    
            return super(SuperuserRequiredMixin, self).dispatch(request, *args, **kwargs)
    

    然后您可以在视图中使用它。我们假设ListView

    from django.views.generic import ListView
    from somewhere import SuperuserRequiredMixin
    
    class MyView(ListView, SuperuserRequiredMixin):
        ...
        # Do what you usually do...
    

    我希望你觉得这很有用。