如何不使用 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_url
:admin.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 的管理员登录视图?的主要内容,如果未能解决你的问题,请参考以下文章