使用django-cas-ng在管理站点上进行身份验证

问题描述:

我正在使用 django-cas-ng 框架对用户进行身份验证。主要问题是管理页面仍使用默认的登录视图。

I'm using django-cas-ng framework to authenticate users. The main problem is that the admin page still uses the default login view.

到目前为止使用的方法:

Methods used this far:

1.-使用env var

来自文档:


CAS_ADMIN_PREFIX:Django管理站点的URL前缀。如果未定义,则CAS中间件将检查正在渲染的视图,以查看其是否存在于django.contrib.admin.views中。

CAS_ADMIN_PREFIX: The URL prefix of the Django administration site. If undefined, the CAS middleware will check the view being rendered to see if it lives in django.contrib.admin.views.






2。-重定向 app / urls.py 上的url:


2.- Redirecting url on app/urls.py:

url(r'^arta/admin/login$',  django_cas_ng.views.login, name='cas_ng_login')

所有内容都将被忽略,并显示管理员登录表单。

Everything is just ignored and the admin login form is shown.

此操作的目标是仅使用CAS并将当前 / app / admin / login 重定向到CAS

The goal of this is to only authenticate with CAS and redirect the current /app/admin/login to CAS

答案是,解决方案是覆盖AdminSite。 Django管理模块会覆盖它自己的URL重定向,因此在 /app/urls.py 中进行编辑是没有用的。

If anyone is interested in the answer, the solution was overriding AdminSite. Django admin module overrides it's own url redirects, so editing them on /app/urls.py was useless.

创建 / app / admin.py 并扩展AdminSite,例如:

Creating an /app/admin.py and extending AdminSite like:

from django.contrib.admin import AdminSite
from functools import update_wrapper
from django.urls import NoReverseMatch, reverse
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.http import Http404, HttpResponseRedirect
import django_cas_ng.views


class Admin(AdminSite):
    def admin_view(self, view, cacheable=False):
        """
        Decorator to create an admin view attached to this ``AdminSite``. This
        wraps the view and provides permission checking by calling
        ``self.has_permission``.

        You'll want to use this from within ``AdminSite.get_urls()``:

            class MyAdminSite(AdminSite):

                def get_urls(self):
                    from django.conf.urls import url

                    urls = super(MyAdminSite, self).get_urls()
                    urls += [
                        url(r'^my_view/$', self.admin_view(some_view))
                    ]
                    return urls

        By default, admin_views are marked non-cacheable using the
        ``never_cache`` decorator. If the view can be safely cached, set
        cacheable=True.
        """
        def inner(request, *args, **kwargs):
            if not self.has_permission(request):
                if request.path == reverse('cas_ng_logout', current_app=self.name):
                    index_path = reverse('admin:index', current_app=self.name)
                    return HttpResponseRedirect(index_path)
                # Inner import to prevent django.contrib.admin (app) from
                # importing django.contrib.auth.models.User (unrelated model).
                from django.contrib.auth.views import redirect_to_login
                return redirect_to_login(
                    request.get_full_path(),
                    reverse('cas_ng_login', current_app=self.name)
                )
            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)

    def get_urls(self):
        from django.conf.urls import url, include
        # Since this module gets imported in the application's root package,
        # it cannot import models from other applications at the module level,
        # and django.contrib.contenttypes.views imports ContentType.
        from django.contrib.contenttypes import views as contenttype_views

        def wrap(view, cacheable=False):
            def wrapper(*args, **kwargs):
                return self.admin_view(view, cacheable)(*args, **kwargs)
            wrapper.admin_site = self
            return update_wrapper(wrapper, view)

        # Admin-site-wide views.
        urlpatterns = [
            url(r'^$', wrap(self.index), name='index'),
            url(r'^login/$', django_cas_ng.views.login, name='login'),
            url(r'^logout/$', django_cas_ng.views.logout, name='logout'),
            url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
            url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
                name='password_change_done'),
            url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
            url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
                name='view_on_site'),
        ]

        # Add in each model's views, and create a list of valid URLS for the
        # app_index
        valid_app_labels = []
        for model, model_admin in self._registry.items():
            urlpatterns += [
                url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
            ]
            if model._meta.app_label not in valid_app_labels:
                valid_app_labels.append(model._meta.app_label)

        # If there were ModelAdmins registered, we should have a list of app
        # labels for which we need to allow access to the app_index view,
        if valid_app_labels:
            regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
            urlpatterns += [
                url(regex, wrap(self.app_index), name='app_list'),
            ]
        return urlpatterns

site = Admin()

然后您覆盖所需的方法,在这种情况下是 admin_view get_urls

Then you override the methods that you want, in this case were admin_view and get_urls

有趣的行是:

admin_v iew

 if request.path == reverse('cas_ng_logout', current_app=self.name):
 ----
 reverse('cas_ng_login', current_app=self.name)

get_urls

url(r'^login/$', django_cas_ng.views.login, name='login'),
url(r'^logout/$', django_cas_ng.views.logout, name='logout')

这将使您将登录和注销步骤重定向到CAS

That will let you redirect the login and logout steps into CAS