使用Django的不同类型的匿名用户

使用Django的不同类型的匿名用户,django,django-authentication,anonymous-users,Django,Django Authentication,Anonymous Users,我目前正在从事的Django项目是一个应该从本地网络和互联网访问的网站。只有匿名用户从本地网络访问站点(基本上是对IP地址的测试),而经过身份验证的用户才能访问整个内容,匿名用户才可以访问部分内容 我想检查一下IP,但在我看来,每次用户加载页面时检查IP是非常糟糕的 有没有一种方法可以干净地存储用户数据,即使是匿名用户?如果能够使用像@login\u required这样的装饰器就好了,但是只有匿名用户有外部IP时,它才会重定向。实际上,在我看来,检查每个请求的IP是可用的最快方法之一。考虑到I

我目前正在从事的Django项目是一个应该从本地网络和互联网访问的网站。只有匿名用户从本地网络访问站点(基本上是对IP地址的测试),而经过身份验证的用户才能访问整个内容,匿名用户才可以访问部分内容

我想检查一下IP,但在我看来,每次用户加载页面时检查IP是非常糟糕的


有没有一种方法可以干净地存储用户数据,即使是匿名用户?如果能够使用像
@login\u required
这样的装饰器就好了,但是只有匿名用户有外部IP时,它才会重定向。

实际上,在我看来,检查每个请求的IP是可用的最快方法之一。考虑到IP已经被加载到每个请求的内存中,您所需要做的就是一个简单的字典查找和比较,以及一个条件字符串拆分/附加的DCT查找。与最简单的页面视图相比,性能影响完全可以忽略,与使用会话或任何其他机制来保存ip的影响相当

您可以使用
user\u passes\u test
编写自己的decorator函数:

from django.contrib.auth.decorators import user_passes_test
from django.utils.decorators import available_attrs
from functools import wraps

LOCAL_IPS = (
    '127.0.0.1',
    'other_ip',
    'etc.',
)

def is_local_request(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip in LOCAL_IPS

def local_ip_required(view_func):
    def wrapped_view(request, *args, **kwargs):
        if not is_local_request(request):
            raise Http404 # or PermissionDenied or redirect
        return view_func(request, *args, **kwargs)
    return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)

然后简单地使用@local\u ip\u required。请注意,此实现将阻止匿名用户和登录用户从外部位置访问视图

实际上,在我看来,检查每个请求的ip是最快的方法之一。考虑到IP已经被加载到每个请求的内存中,您所需要做的就是一个简单的字典查找和比较,以及一个条件字符串拆分/附加的DCT查找。与最简单的页面视图相比,性能影响完全可以忽略,与使用会话或任何其他机制来保存ip的影响相当

您可以使用
user\u passes\u test
编写自己的decorator函数:

from django.contrib.auth.decorators import user_passes_test
from django.utils.decorators import available_attrs
from functools import wraps

LOCAL_IPS = (
    '127.0.0.1',
    'other_ip',
    'etc.',
)

def is_local_request(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip in LOCAL_IPS

def local_ip_required(view_func):
    def wrapped_view(request, *args, **kwargs):
        if not is_local_request(request):
            raise Http404 # or PermissionDenied or redirect
        return view_func(request, *args, **kwargs)
    return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)

然后简单地使用@local\u ip\u required。请注意,此实现将阻止匿名用户和登录用户从外部位置访问视图

这不是我们的目的吗?这不是我们的目的吗?谢谢,我没有意识到定义decorator这么容易,我应该能够很容易地将它调整到所需的
@authentication\u或\u local\u ip\u
。在我的例子中,只是一个小细节,本地IP被定义为一组范围,如
192.168.1.*
,是否有一个简单的快捷方式来测试它,或者我应该实现字符串比较?有几种方法。寻找那些支持范围并提供
\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
实现的,然后挑选一个。如果您熟悉网络掩码:大多数软件包似乎都使用它来代替通配符。如果您不熟悉:您应该是:P,但至少支持
('192.168.1.0','192.168.1.255'),
形式的范围。谢谢,我没有意识到定义装饰器这么容易,我应该能够轻松地将其适应
@身份验证或所需的本地ip
。在我的例子中,只是一个小细节,本地IP被定义为一组范围,如
192.168.1.*
,是否有一个简单的快捷方式来测试它,或者我应该实现字符串比较?有几种方法。寻找那些支持范围并提供
\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
实现的,然后挑选一个。如果您熟悉网络掩码:大多数软件包似乎都使用它来代替通配符。如果您不熟悉:您应该是:P,但至少支持
形式的范围(('192.168.1.0','192.168.1.255'),)