在Django中通过IP地址进行身份验证

Mad*_*ist 13 python authentication django

我有一个小的Django应用程序,我想限制某些用户.来自特定网络的任何人都应该能够在没有任何进一步身份验证的情况下看到该视图,仅基于IP地址.应该要求来自此IP范围之外的任何其他人使用密码并根据默认的Django用户管理进行身份验证.

我假设我必须为此编写自定义身份验证后端,但文档让我感到困惑,因为authenticate()函数似乎需要用户名/密码组合或令牌.我不清楚如何使用IP地址进行身份验证.

在Django中实现基于IP地址的身份验证的正确方法是什么?我宁愿尽可能多地使用现有的库函数来处理与安全相关的代码,而不是自己编写所有代码.

Fal*_*gel 11

这种身份验证有两种合适的方法:

  • 作为Decorator:如果一些视图(但不是很多)需要这样的检查,那么最好为它编写一个装饰器(像@Jingo写的那样)
  • 作为中间件:如果该检查需要由所有(或许多)视图完成,而不是使用装饰器,编写中间件是更好的解决方案.

示例中间件可以是:

ALLOWED_IP_BLOCKS = [......]

class NeedToLoginMiddleware(object):
    def process_request(self, request):
        ip = request.META['REMOTE_ADDR']
        if not ip in ALLOWED_IP_BLOCKS: #ip check
            if not request.user.is_authenticated(): #if ip check failed, make authentication check
                return HttpResponseRedirect(...)
        return None
Run Code Online (Sandbox Code Playgroud)
  • 你可以使用列表进行ip检查,或者像@Jingo提到的那样使用正则表达式进行ip检查.
  • 如果您使用的是django身份验证REMOTE_ADDR且不在ALLOWED_IP_BLOCKS列表中,则可以使用它is_authenticated来检查相关用户是否已登录.但是对于is_authenticated在自定义中间件中使用,必须放置 自定义中间件AuthenticationMiddleware,因为request.user在该级别上设置.

    MIDDLEWARE_CLASSES = (
        ...
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'path.to.my.NeedToLoginMiddleware',
        ...
    )
    
    Run Code Online (Sandbox Code Playgroud)
    • 如果一些视图不需要此身份验证,那么您可以创建例外URL列表并从中获取请求URL request.path并检查请求URL是否需要ip检查/身份验证.

有关自定义中间件类的更多信息

  • 将 `ALLOWED_IP_BLOCKS` 放入 *settings.py*,并使用 `settings.ALLOWED_IP_BLOCKS` 访问它(需要 `from django.conf import settings`)将允许更好的配置, (3认同)

Jin*_*ngo 7

您还可以为此目的编写一个小装饰器:

def login_by_ip(view_func):
    def authorize(request, *args, **kwargs):
        user_ip = request.META['REMOTE_ADDR']
        for ip in allowedIps.allowedIps:
            authenticated_by_ip = re.compile(ip).match(user_ip)
            if authenticated_by_ip:
                return view_func(request, authenticated_by_ip, *args, **kwargs)
        return HttpResponseRedirect('/redirect/path/')
    return authorize
Run Code Online (Sandbox Code Playgroud)

allowedIps在我的例子中是一个文件(allowedIps.py),它在这样的元组中存储允许的IP的正则表达式:

allowedIps = ('^XXX\.XXX\..+\..+$','^XXX\.XXX\.XXX\..+$', '^XXX\.XXX\.XXX\.XXX$')
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助或提出一个想法.注意:如果将authenticated_by_ip返回到装饰视图,则视图必须接受该参数,如果不需要,也可以省略它.您还可以更精确地定义正则表达式,以仅接受最多三个数字.


Pau*_*ipp 5

IMO,如果它是一个小型的非性能关键站点,那么使用 Django 解决这个问题就可以了。

最好使用 Apache 或 Nginx 服务来完全阻止未经授权的用户。例如,在 Nginx 中,我的站点配置中有以下几行:

include allowed_ips.conf;
deny all;
error_page 403 forbidden.html;
Run Code Online (Sandbox Code Playgroud)

allowed_ips.conf 位于 /etc/nginx 中,看起来像这样:

allow 110.222.333.222;  # J Bloggs (sys admin)
allow 777.222.0.0/16;   # Government owned
...
Run Code Online (Sandbox Code Playgroud)

我相信这更好,因为相对较慢的 Django 进程永远不会受到阻止的 IP 的影响。如果您出于性能或安全原因阻止机器人或其他国家/地区地址范围,这一点非常重要。


Hed*_*ide 3

无需为您编写的用例编写身份验证后端。在中间件层编写一个基于 IP 的调度程序可能就足够了

如果您的应用程序的 url 匹配,process_request 应检查经过身份验证的 django 用户并将该用户与白名单匹配。