【问题标题】:How to restrict non staff users from accessing django-admin如何限制非员工用户访问 django-admin
【发布时间】:2021-03-17 12:46:27
【问题描述】:

我的 django-admin 页面位于

http://127.0.0.1:8000/admin/

假设我的网站有 3 个用户。

  1. 超级用户
  2. 员工
  3. 最终用户

如果这三个用户中的任何一个尝试访问此链接http://127.0.0.1:8000/admin/,第一个和第二个都可以访问它。 最终用户无法访问它。到此为止就好了。

我想要做的是向最终用户显示错误 404。他/她不应该知道这个链接是用于管理页面的。此外,如果有人没有登录,他们也应该看到相同的 404 页面。

我已经引用了this 链接,但它会将我带到另一个默认页面。

PFA 相同



PS:我使用的是Signin With Google,所以它不应该将我重定向到那里。

自从连续 3 天以来我一直在尝试这个,所以非常感谢任何帮助。提前致谢。

Django 版本:3. 0. 5

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    您首先需要制作一个自定义装饰器,如果用户不是员工,它会给出 404:

    from django.http import Http404
    from functools import wraps
    
    def staff_required(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            if request.user.is_staff:
                return func(request, *args, **kwargs)
            raise Http404()
        return wrapper
    

    接下来,我们将按照您的链接问题中的描述使用此装饰器:

    from django.contrib import admin
    
    admin.site.login = staff_required(admin.site.login)
    
    urlpatterns = [
        path('admin/', admin.site.urls),
    ]
    

    编辑:上面的方法有点笨拙,即使它给出了 404 错误,它也会向用户显示登录页面 url。最好制作一个自定义管理站点类并使用它。管理站点有一个方法admin_view,它装饰了我们将覆盖的管理视图。我们将在项目主应用程序中的文件admin.py 中执行此操作(假设项目名为myproject

    from functools import update_wrapper
    
    from django.contrib import admin
    from django.http import (
        Http404, HttpResponseRedirect,
    )
    from django.urls import reverse
    from django.views.decorators.cache import never_cache
    from django.views.decorators.csrf import csrf_protect
    
    
    class MyAdminSite(admin.AdminSite):
        def admin_view(self, view, cacheable=False):
            def inner(request, *args, **kwargs):
                if not self.has_permission(request):
                    if request.path == reverse('admin:logout', current_app=self.name):
                        index_path = reverse('admin:index', current_app=self.name)
                        return HttpResponseRedirect(index_path)
                    raise Http404()
                return view(request, *args, **kwargs)
            if not cacheable:
                inner = never_cache(inner)
            # We add csrf_protect here so this function can be used as a utility
            # function for any view, without having to repeat 'csrf_protect'.
            if not getattr(view, 'csrf_exempt', False):
                inner = csrf_protect(inner)
            return update_wrapper(inner, view)
    

    现在我们需要用我们的自定义管理站点替换默认管理站点。为此,我们将关注Overriding the default admin site [Django docs]

    在项目主应用程序的apps.py 文件中(假设项目被命名为myproject):

    from django.contrib.admin.apps import AdminConfig
    
    class MyAdminConfig(AdminConfig):
        default_site = 'myproject.admin.MyAdminSite'
    

    现在在settings.py 中,我们将用我们自己的配置类替换'django.contrib.admin'

    INSTALLED_APPS = [
        ...
        'myproject.apps.MyAdminConfig',  # replaces 'django.contrib.admin'
        ...
    ]
    

    【讨论】:

    • 我应该在哪个文件中为管理员写custom decorator。以前从未使用过这个。任何推荐链接也是值得赞赏的
    • @ajinzrathod althoug 你可以把它写在你的urls.py 中,最好把它写在一些不同的文件中,比如说命名为decorators.py (如果你写在不同的文件中,请记住导入装饰器)。
    • wrapper() missing 1 required positional argument: 'request' 截图:imgur.com/bI7bdT1
    • @ajinzrathod 也许method_decorator 不需要?所以admin.site.login = staff_required(admin.site.login)。无论如何,这种方法仍然有点老套,我在答案中添加了一种更好的方法。
    • @ajinzrathod 在那个方法中我们装饰admin.site.login,这基本上意味着覆盖登录视图。会发生什么情况是用户首先会被重定向到登录视图,然后他们将获得 404,因此由于重定向,即使他们只有写了/admin/,这表明那里实际上有一个页面。
    猜你喜欢
    • 1970-01-01
    • 2012-04-28
    • 2015-08-19
    • 2015-12-24
    • 1970-01-01
    • 2022-11-05
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    相关资源
    最近更新 更多