如何不使用 Django 的管理员登录视图?

Posted

技术标签:

【中文标题】如何不使用 Django 的管理员登录视图?【英文标题】:How can I not use Django's admin login view? 【发布时间】:2011-10-10 09:24:19 【问题描述】:

我创建了自己的登录视图。但是,如果用户直接进入 /admin,它会将他们带到管理员登录页面并且不使用我的自定义视图。我怎样才能让它重定向到用于所有非 /admin 的登录视图?

【问题讨论】:

艾萨克的回答对我来说非常有效。你应该接受他的回答! :) 【参考方案1】:

来自http://djangosnippets.org/snippets/2127/ - 使用login_required 包装管理员登录页面。例如在urls.py:

from django.contrib.auth.decorators import login_required
from django.contrib import admin
admin.autodiscover()
admin.site.login = login_required(admin.site.login)

你可能已经有了中间两行,甚至可能是第一行;添加第四行将导致任何可能命中admin.site.login 函数的内容都使用适当的next 参数重定向到您的LOGIN_URL

【讨论】:

假设我已经以编外用户身份登录。如果我然后转到/admin/,我仍然会得到默认登录表单,因为login_required 不会触发。 我已经在自己的回答中解决了@PēterisCaune 的担忧。【参考方案2】:

我发现上面的答案没有正确尊重“下一个”查询参数。

解决此问题的一种简单方法是使用简单的重定向。在您网站的 urls 文件中,立即 包括管理员 url 之前,输入如下一行:

   url(r'^admin/login$', RedirectView.as_view(pattern_name='my_login_page', permanent=True, query_string=True))

【讨论】:

更好,url(r'^admin/login/$', RedirectView.as_view(url=settings.LOGIN_URL, permanent=True, query_string=True)),【参考方案3】:

虽然@Isaac 的解决方案应该拒绝大多数恶意机器人,但它并没有为专业渗透提供保护。登录用户在尝试登录管理员时收到以下消息:

我们应该使用 admin 装饰器来拒绝所有非特权用户:

from django.contrib.admin.views.decorators import staff_member_required
from django.contrib import admin
[ ... ]
admin.site.login = staff_member_required(admin.site.login, login_url=settings.LOGIN_URL)

据我所知,装饰器在 1.9 中是 added。

【讨论】:

我完全有可能(很可能)在做一些愚蠢的事情,但是当我这样做时,我最终会出现一个重定向循环,其中/admin/login/ 重定向到/admin/login/?next=/admin/login/,它重定向到@987654327 @等 @Isaac 这里有必要通过login_urladmin.site.login = staff_member_required(admin.site.login, login_url=settings.LOGIN_URL) OP,您介意编辑您的答案以包含@blueyed 提供的信息以避免重定向吗? 我想补充一点,我已经为这个问题寻找了几个小时的解决方案,只有你的答案实现了我想要做的 - 非常感谢。 - 只是想知道,有没有办法将编外人员或未经身份验证的用户重定向到例如 404 页面而不是登录页面?【参考方案4】:

你好 我找到了一个非常简单的解决方案。 只需告诉 django 管理员登录的 url 由您自己的登录视图处理

你只需要修改项目的urls.py文件(注意,不是应用程序)

    在您的 PROJECT 文件夹中找到文件 urls.py。 将此行添加到导入部分from your_app_name import views 找到此行url(r'^admin/', include(admin.site.urls)) 在该行上方添加以下内容url(r'^admin/login/', views.your_login_view),

这是一个例子

    from django.conf.urls import include, url
    from django.contrib import admin

    from your_app import views

    urlpatterns = [
        url(r'^your_app_start/', include('your_app.urls',namespace="your_app_name")),

        url(r'^admin/login/', views.your_app_login),
        url(r'^admin/', include(admin.site.urls)),
    ]

【讨论】:

【参考方案5】:

http://blog.montylounge.com/2009/07/5/customizing-django-admin-branding/ (web archive)

我正在尝试解决这个问题,我在这个家伙的博客上找到了解决方案。基本上,覆盖管理模板并使用您自己的模板。简而言之,只需在 /path-to-project/templates/admin/ 中创建一个名为 login.html 的文件,它将替换管理员登录页面。您可以复制原始文件(django/contrib/admin/templates/login.html)并修改一两行。如果您想完全取消默认登录页面,您可以执行以下操作:

% extends "my-login-page.html" %

就是这样。一个文件中的一行。 Django 很棒。

【讨论】:

【参考方案6】:

我遇到了同样的问题,尝试使用已接受的answer,但与comment above 中指出的问题相同。 然后我做了一些不同的事情,如果这对某人有帮助,请粘贴在这里。

def staff_or_404(u):
    if u.is_active:
        if u.is_staff:
            return True
        raise Http404()
    return False

admin.site.login = user_passes_test(
        staff_or_404,
    )(admin.site.login)

这个想法是,如果用户登录,并尝试访问管理员,那么他会得到 404。否则,它将强制您进入正常的登录页面(除非您已经登录)

【讨论】:

【参考方案7】:

在你的 ROOT_URLCONF 文件中(默认情况下,它是项目根文件夹中的 urls.py),是否有这样一行:

urlpatterns = patterns('',
...
    (r'^admin/', include(admin.site.urls)),
...
)

如果是这样,您希望将 include(admin.site.urls) 替换为您创建的自定义视图:

(r'^admin/', 'myapp.views.myloginview'),

或者如果你的应用有自己的 urls.py,你可以像这样包含它:

(r'^admin/', include(myapp.urls)),

【讨论】:

为了澄清我想继续使用管理员,我只希望不使用登录管理员视图。通过替换 include(admin.site.urls)) 我无法再访问 /admin 了。 所以您想通过与登录系统其余部分相同的登录视图登录管理系统?让视图知道登录用户是否想要常规登录与管理员登录的机制是什么? Obv 如果用户没有管理员凭据,他们将无法进行管理员登录,但如果他们有管理员凭据,他们是否希望以登录用户或登录管理员的身份查看该站点? 在我的例子中,管理员用户永远不需要访问网站的非管理员部分。所以我的观点根据他们是什么类型的用户来重定向他们。所以是的,我希望他们看到非管理员用户会看到的相同登录名。如果转到 / 已经发生这种情况,但是如果他们在 /admin 中为某些内容添加书签,它会将它们发送到管理员的登录名,这是我不希望发生的。 因此管理员用户转到 /,使用所有用户看到的通用登录视图登录,然后为管理员视图提供服务。您担心他们会将 /admin/whatever 加入书签,然后当他们稍后返回该书签时,他们将获得管理视图而不是常见的登录视图。对吗? 是的。我希望所有登录代码都由同一个视图处理,因为我有一些处理 Google Apps 身份验证的自定义代码。它有时需要显示登录成功或失败之外的特殊消息。【参考方案8】:

这是我使用custom AdminSite class 的解决方案:

class AdminSite(admin.AdminSite):

    def _is_login_redirect(self, response):
        if isinstance(response, HttpResponseRedirect):
            login_url = reverse('admin:login', current_app=self.name)
            response_url = urllib.parse.urlparse(response.url).path
            return login_url == response_url
        else:
            return False

    def admin_view(self, view, cacheable=False):
        inner = super().admin_view(view, cacheable)

        def wrapper(request, *args, **kwargs):
            response = inner(request, *args, **kwargs)
            if self._is_login_redirect(response):
                if request.user.is_authenticated():
                    return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
                else:
                    return redirect_to_login(request.get_full_path(), reverse('accounts_login'))
            else:
                return response

        return wrapper

【讨论】:

【参考方案9】:

您可以将管理员登录网址重定向到身份验证登录视图:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('', include('your_app.urls')),
    path('accounts/', include('django.contrib.auth.urls')),
    path('admin/login/', RedirectView.as_view(url='/accounts/login/?next=/admin/', permanent=True)),
    path('admin/', admin.site.urls),
]

【讨论】:

【参考方案10】:

截至 2020 年 8 月,django.contrib.admin.sites.AdminSite 具有 login_template 属性。所以你可以只继承AdminSite 并指定一个自定义模板,即,

class MyAdminSite(AdminSite):
    login_template = 'my_login_template.html'

my_admin_site = MyAdminSite()

然后在任何地方都使用my_admin_site 而不是admin.site

【讨论】:

以上是关于如何不使用 Django 的管理员登录视图?的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中,只允许管理员用户访问视图

Django 自定义登录视图 -> 会话不持久

django admin:单独的只读视图和更改视图

django如何实现管理员只能登录后台,不能登录前台网站?

Django框架:视图模板

如何从视图中呈现特定的 Django 管理页面?