22👍
I ended up writing a middleware for it:
from django.core.urlresolvers import reverse
from django.http import Http404
class RestrictStaffToAdminMiddleware(object):
"""
A middleware that restricts staff members access to administration panels.
"""
def process_request(self, request):
if request.path.startswith(reverse('admin:index')):
if request.user.is_authenticated():
if not request.user.is_staff:
raise Http404
else:
raise Http404
6👍
Overwrite the admin_view part of the AdminSite class before using it in the urls.
In admin.py file (create it if you don’t have it) add:
from functools import update_wrapper
from django.http import Http404
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
def admin_view(view, cacheable=False):
"""
Overwrite the default admin view to return 404 for not logged in users.
"""
def inner(request, *args, **kwargs):
if not request.user.is_active and not request.user.is_staff:
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)
and then in your urls file add:
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.views.defaults import page_not_found
from my_project.admin import admin_view
admin.site.admin_view = admin_view
urlpatterns = patterns('',
url(r'^admin/login/', page_not_found),
url(r'^admin/', include(admin.site.urls)),
)
Of course if you still want the login to be found then remove the url(r’^admin/login/’, page_not_found) line.
1👍
If you’re using the default Django admin pages, Django already has built-in control to restrict access to those pages. The is_staff
Boolean for a user model controls whether the user has access to the Django admin pages. The is_superuser
Boolean controls whether the user has all privileges without explicitly assigning them. Note, however, that is_superuser
will not grant access to the Django admin pages; you must set is_staff
to True regardless of the value of is_superuser
for a user to have access to the Django admin pages.
https://docs.djangoproject.com/en/1.6/ref/contrib/auth/#django.contrib.auth.models.User.is_staff
But I don’t know if Django will raise a 404 if a non-staff user tries to access the Django admin interface.
1👍
I created an updated version of @ip.’s middleware. This uses process_view
to directly check if the view is a member of the admin site, rather than just checking if the URL is on the admin site. It also adds a warning log entry if an unauthorized user attempts to access the admin site, and simplifies the if
logic. This is written for Python 3 and Django 2.
from inspect import getmodule
import django.contrib.admin.sites
from django.http import Http404
import logging
logger = logging.getLogger(__name__)
class RestrictStaffToAdminMiddleware:
"""
A middleware that restricts staff members access to administration panels.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
module = getmodule(view_func)
if (module is django.contrib.admin.sites) and (not request.user.is_staff):
ip = request.META.get('HTTP_X_REAL_IP', request.META.get('REMOTE_ADDR'))
ua = request.META.get('HTTP_USER_AGENT')
logger.warn(f'Non-staff user "{request.user}" attempted to access admin site at "{request.get_full_path()}". UA = "{ua}", IP = "{ip}", Method = {request.method}')
raise Http404
0👍
You can create your own admin_login_required decorator.
The decorator should check if there is a user and if the user is an admin type. If there is no user, of if the user is not an admin, you can redirect to a login page or display a message saying user is unauthorized.
Here’s a good example how to write a decorator for a django view. http://passingcuriosity.com/2009/writing-view-decorators-for-django/
The page described an example of anonymous_required decorator where user has to be anonymous.
You can take that example and implement an admin_login_required decorator using the specs I provided above, or come up with your own scenarios.
Good luck.
0👍
You can use this package django-admin-ip-restrictor and set ip restriction for Admin view only.
To install package :
pip install django-admin-ip-restrictor
Exemple in your settings.py
MIDDLEWARE = [
...,
admin_ip_restrictor.middleware.AdminIPRestrictorMiddleware
]
RESTRICT_ADMIN=True
ALLOWED_ADMIN_IPS=['127.0.0.1']
ALLOWED_ADMIN_IP_RANGES=['127.0.0.0/24']
RESTRICTED_APP_NAMES=['admin']
TRUST_PRIVATE_IP=True
- Django-compressor: how to write to S3, read from CloudFront?
- Remove padding from matplotlib plotting
- How can I rename a column label in Django Admin for a field that is a method//property?
- 'Questions ' object is not iterable Django
- Pycharm (Python IDE) doesn't auto complete Django modules
0👍
Here is the code of @ip that works(make sure it is after authentication middleware in settings.py
middleware list)
from django.urls import reverse
from django.http import Http404
from django.utils.deprecation import MiddlewareMixin
class RestrictNormalToAdmin(MiddlewareMixin):
def process_request(self, request):
if request.path.startswith(reverse('admin:index')):
if request.user.is_authenticated:
if not request.user.is_staff:
raise Http404
else:
raise Http404
- Django dynamic urls
- You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware
- Django filter on APIView
- Django & the "TemplateDoesNotExist" error
0👍
In Django 4.2 middleware, the function process_request
is not called anymore. Here is updated version of accepted answer.
from django.http import Http404
from django.urls import reverse
class RestrictStaffToAdminMiddleware(object):
"""
A middleware that restricts staff members access to administration panels.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.path.startswith(reverse("admin:index")):
if request.user.is_authenticated:
if not request.user.is_staff:
raise Http404
else:
raise Http404
return self.get_response(request)
See also Django documentation
- Django override the form HTML label template?
- Django template img src not working
- Why does Django South 1.0 use iteritems()?
- In django, is aggregate(Count()) faster or better than .count() in anyway?
- How to resolve the "psycopg2.errors.UndefinedTable: relation "auth_user" does not exist" when running django unittests on Travis