Найти - Пользователи
Полная версия: добавить дополнительную проверку при логине в админку
Начало » Django » добавить дополнительную проверку при логине в админку
1
botinag
накидал следующую мидлварь…
from django.conf import settings
from django import http
class SuperUserIpRestrictMiddleware(object):
    """
    Разрешает доступ суперпользователям только с определенных ip
    список разрешенных ip = settings.SUPERUSER_ALLOWED_IP
    """
    def process_request(self, request):
        if (request.user.is_superuser and request.path != u'/logout/' and 
                request.META['REMOTE_ADDR'] not in 
                settings.SUPERUSER_ALLOWED_IP):
            html_str = u'''
                <h1>Доступ запрещен</h1>Вход с ip {ip} для 
                пользователя <b>{user}</b> запрещен.</br>
                <a href="/logout/">Вернуться</a>
                '''.format(ip=request.META['REMOTE_ADDR'], user=request.user)
            return http.HttpResponseForbidden(html_str)
        return None
теперь вот думаю, что выглядит не слишком красиво.
а красиво бы выглядело, если как при несовпадении логина/пароля выскакивал соответствыющий ValidationError.
я думал сделать следующим образом:
сделать кастомную форму, унаследованную от AuthenticationForm и переопределить там clean()…
но как мне в clean передавать вещи, начинающиеся с request?
чтобы реализовать что-то типа:
def clean(self):
...
if request.user.is_superuser and request.META['REMOTE_ADDR'] != u'127.0.0.1':
    raise ValidationError(u'доступ запрещен')
PanovSergey
botinag
накидал следующую мидлварь…
Вы определитесь сначала вам надо чтобы работало на каждый запрос(middleware) или только на форме входа(Form)
botinag
PanovSergey
Вы определитесь сначала вам надо чтобы работало на каждый запрос(middleware) или только на форме входа(Form)
как я себе вижу ситуацию:
все стандартные вещи в админке доступны только после логина и все мои собственные вьюхи требуют логина => мне достаточно, чтобы ip проверялся только на форме входа.
был бы признателен за пример кода для моего случая.
PanovSergey
botinag
как я себе вижу ситуацию:
все стандартные вещи в админке доступны только после логина и все мои собственные вьюхи требуют логина => мне достаточно, чтобы ip проверялся только на форме входа.
был бы признателен за пример кода для моего случая.
Значит вам надо для каждой въюхи требовать вход. Обычно делается декоратором login_required
Дальше во вью login пишете обработку. Миддлваре тут не нужен.
Если для какой то вью нужны доп проверки есть еще декоратор user_passes_test
botinag
PanovSergey
Значит вам надо для каждой въюхи требовать вход. Обычно делается декоратором login_required
мои самописные вьюхи снабжены декоратором.
PanovSergey
Дальше во вью login пишете обработку. Миддлваре тут не нужен.
я как раз хочу отказаться от миддлварь. вот я не совсем понимаю как во вьюхе сделать, чтобы при попытке логина с ip не из моего списка выскакивал ValidationError для формы логина.
—–
например при несовпадении логина и пароля на странице входа в админку, выскакивает следующее оповещение (я использую django-grappelli):

я хочу, чтобы выскакивало подобное сообщение с моим текстом, но для суперюзеров, пытающихся залогинится с ip, не входящих в мой список.
PanovSergey
вот я не совсем понимаю как во вьюхе сделать, чтобы при попытке логина с ip не из моего списка выскакивал ValidationError для формы логина.
Отнаследуйтесь от формы логина, передавайте ей параметр
current_ip=request.META['REMOTE_ADDR']
. В методе clean сделайте проверку.
Типа этого
botinag
накидал следующего кадавра:
urls.py:
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.generic import TemplateView
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
from accounts.forms import MyAuthenticationForm
urlpatterns = patterns('',
...
    url(r'^login/',
        'accounts.views.custom_login',
        {'authentication_form': MyAuthenticationForm},
        name='auth_login'),
)
urlpatterns += staticfiles_urlpatterns()

accounts/views.py:
from accounts.forms import MyAuthenticationForm
from django.core.exceptions import ValidationError
from django.contrib.auth.views import login
from django import forms
from django.shortcuts import redirect
from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login
from django.utils.http import base36_to_int, is_safe_url
from django.shortcuts import resolve_url
from django.http import HttpResponseRedirect, QueryDict
def custom_login(request, template_name='login.html',
                 redirect_field_name=REDIRECT_FIELD_NAME,
                 authentication_form=MyAuthenticationForm,
                 current_app=None, extra_context=None):
                 
    redirect_to = request.REQUEST.get(redirect_field_name, '')
    if request.method == 'POST':
        form = MyAuthenticationForm(
            data=request.POST, current_ip=request.META['REMOTE_ADDR'], 
            user=request.user, request=request
        )
        if form.is_valid():
            # Ensure the user-originating redirection url is safe.
            if not is_safe_url(url=redirect_to, host=request.get_host()):
                redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
            # Okay, security check complete. Log the user in.
            auth_login(request, form.get_user())
            if request.session.test_cookie_worked():
                request.session.delete_test_cookie()
            return HttpResponseRedirect(redirect_to)
    else:
        form = MyAuthenticationForm(current_ip=request.META['REMOTE_ADDR'], 
                                    user=request.user, request=request)
    request.session.set_test_cookie()
    current_site = get_current_site(request)
    context = {
        'form': form,
        redirect_field_name: redirect_to,
        'site': current_site,
        'site_name': current_site.name,
    }
    if extra_context is not None:
        context.update(extra_context)
    return TemplateResponse(request, template_name, context,
                            current_app=current_app)

accounts/forms.py:
from django.contrib.auth.forms import AuthenticationForm
from django import forms
class MyAuthenticationForm(AuthenticationForm):
    current_ip = forms.IPAddressField()
    
    def __init__(self, current_ip=None, user=None, request=None, *args, **kwargs):
        self.current_ip = current_ip
        self.request = request
        self.user_cache = None
        self.user = user
        super(MyAuthenticationForm, self).__init__(*args, **kwargs)
        UserModel = get_user_model()
        self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD)
        if not self.fields['username'].label:
            self.fields['username'].label = capfirst(self.username_field.verbose_name)
    def clean_current_ip(self):
        current_ip = self.cleaned_data.get('current_ip')
        if self.user.is_superuser() and current_ip != u'127.0.0.1':
            raise forms.ValidationError(u'try from another ip!')
        return current_ip

пока при попытке зайти на страницу логина выдает 404 ошибку.
login.html лежит в папке templates

как сие исправить?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB