mirror of
https://github.com/jazzband/django-axes.git
synced 2026-03-16 22:30:23 +00:00
parent
700ea46607
commit
cd950ddfef
5 changed files with 50 additions and 14 deletions
|
|
@ -5,7 +5,6 @@ from string import Template
|
|||
from typing import Callable, Optional, Type, Union
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import ipware.ip
|
||||
from django.core.cache import BaseCache, caches
|
||||
from django.http import HttpRequest, HttpResponse, JsonResponse, QueryDict
|
||||
from django.shortcuts import redirect, render
|
||||
|
|
@ -16,6 +15,13 @@ from axes.models import AccessBase
|
|||
|
||||
log = getLogger(__name__)
|
||||
|
||||
try:
|
||||
import ipware.ip
|
||||
|
||||
IPWARE_INSTALLED = True
|
||||
except ImportError:
|
||||
IPWARE_INSTALLED = False
|
||||
|
||||
|
||||
def get_cache() -> BaseCache:
|
||||
"""
|
||||
|
|
@ -148,20 +154,24 @@ def get_client_username(
|
|||
return request_data.get(settings.AXES_USERNAME_FORM_FIELD, None)
|
||||
|
||||
|
||||
def get_client_ip_address(request: HttpRequest) -> str:
|
||||
def get_client_ip_address(
|
||||
request: HttpRequest,
|
||||
use_ipware: Optional[bool] = None,
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
Get client IP address as configured by the user.
|
||||
|
||||
The order of preference for address resolution is as follows:
|
||||
|
||||
1. If configured, use ``AXES_CLIENT_IP_CALLABLE``, and supply ``request`` as argument
|
||||
2. Use django-ipware package (parameters can be configured in the Axes package)
|
||||
2. If available, use django-ipware package (parameters can be configured in the Axes package)
|
||||
3. Use ``request.META.get('REMOTE_ADDR', None)`` as a fallback
|
||||
|
||||
:param request: incoming Django ``HttpRequest`` or similar object from authentication backend or other source
|
||||
"""
|
||||
|
||||
if settings.AXES_CLIENT_IP_CALLABLE:
|
||||
log.debug("Using settings.AXES_CLIENT_IP_CALLABLE to get username")
|
||||
log.debug("Using settings.AXES_CLIENT_IP_CALLABLE to get client IP address")
|
||||
|
||||
if callable(settings.AXES_CLIENT_IP_CALLABLE):
|
||||
return settings.AXES_CLIENT_IP_CALLABLE( # pylint: disable=not-callable
|
||||
|
|
@ -173,15 +183,26 @@ def get_client_ip_address(request: HttpRequest) -> str:
|
|||
"settings.AXES_CLIENT_IP_CALLABLE needs to be a string, callable, or None."
|
||||
)
|
||||
|
||||
client_ip_address, _ = ipware.ip.get_client_ip(
|
||||
request,
|
||||
proxy_order=settings.AXES_PROXY_ORDER,
|
||||
proxy_count=settings.AXES_PROXY_COUNT,
|
||||
proxy_trusted_ips=settings.AXES_PROXY_TRUSTED_IPS,
|
||||
request_header_order=settings.AXES_META_PRECEDENCE_ORDER,
|
||||
)
|
||||
# Resolve using django-ipware from a configuration flag that can be set to False to explicitly disable
|
||||
# this is added to both enable or disable the branch when ipware is installed in the test environment
|
||||
if use_ipware is None:
|
||||
use_ipware = IPWARE_INSTALLED
|
||||
if use_ipware:
|
||||
log.debug("Using django-ipware to get client IP address")
|
||||
|
||||
return client_ip_address
|
||||
client_ip_address, _ = ipware.ip.get_client_ip(
|
||||
request,
|
||||
proxy_order=settings.AXES_PROXY_ORDER,
|
||||
proxy_count=settings.AXES_PROXY_COUNT,
|
||||
proxy_trusted_ips=settings.AXES_PROXY_TRUSTED_IPS,
|
||||
request_header_order=settings.AXES_META_PRECEDENCE_ORDER,
|
||||
)
|
||||
return client_ip_address
|
||||
|
||||
log.debug(
|
||||
"Using request.META.get('REMOTE_ADDR', None) fallback method to get client IP address"
|
||||
)
|
||||
return request.META.get("REMOTE_ADDR", None)
|
||||
|
||||
|
||||
def get_client_user_agent(request: HttpRequest) -> str:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ Installation
|
|||
|
||||
Axes is easy to install from the PyPI package::
|
||||
|
||||
$ pip install django-axes
|
||||
$ pip install django-axes[ipware] # use django-ipware for resolving client IP addresses OR
|
||||
$ pip install django-axes # implement and configure custom AXES_CLIENT_IP_CALLABLE
|
||||
|
||||
After installing the package, the project settings need to be configured.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
-e .
|
||||
django-ipware>=3
|
||||
coverage==7.2.3
|
||||
pytest==7.3.1
|
||||
pytest-cov==4.0.0
|
||||
|
|
|
|||
5
setup.py
5
setup.py
|
|
@ -36,7 +36,10 @@ setup(
|
|||
use_scm_version=True,
|
||||
setup_requires=["setuptools_scm"],
|
||||
python_requires=">=3.7",
|
||||
install_requires=["django>=3.2", "django-ipware>=3", "setuptools"],
|
||||
install_requires=["django>=3.2", "setuptools"],
|
||||
extras_require={
|
||||
"ipware": "django-ipware>=3",
|
||||
},
|
||||
include_package_data=True,
|
||||
packages=find_packages(exclude=["tests"]),
|
||||
classifiers=[
|
||||
|
|
|
|||
|
|
@ -614,6 +614,16 @@ class ClientIpAddressTestCase(AxesTestCase):
|
|||
with self.assertRaises(TypeError):
|
||||
get_client_ip_address(HttpRequest())
|
||||
|
||||
def test_get_client_ip_address_with_ipware(self):
|
||||
request = HttpRequest()
|
||||
request.META["REMOTE_ADDR"] = "127.0.0.2"
|
||||
self.assertEqual(get_client_ip_address(request, use_ipware=True), "127.0.0.2")
|
||||
|
||||
def test_get_client_ip_address_without_ipware(self):
|
||||
request = HttpRequest()
|
||||
request.META["REMOTE_ADDR"] = "127.0.0.3"
|
||||
self.assertEqual(get_client_ip_address(request, use_ipware=False), "127.0.0.3")
|
||||
|
||||
|
||||
class IPWhitelistTestCase(AxesTestCase):
|
||||
def setUp(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue