Как написать пользовательский бэкенд аутентификации только для одной конечной точки (/metrics) в Django?
У меня есть пользовательское промежуточное ПО в Django, которое заставляет все запросы проходить через аутентификацию входа (за некоторыми исключениями, такими как api/token).
Этот проект позволяет пользователям аутентифицироваться либо через JWT-токен, либо через логин в
/admin/login и все неаутентифицированные пользователи перенаправляются на /admin/login. для аутентификации.
Мы развернули проект в Kubernetes и хотим, чтобы Prometheus скреативил конечную точку /metrics, но не хотим, чтобы она была открыта для неаутентифицированных пользователей. Prometheus позволяет аутентифицироваться с помощью username и password. Дело в том, что когда запрос отправляется на /metrics, из-за промежуточного программного обеспечения запрос перенаправляется на /admin/login.
Поэтому я считаю, что мне нужно написать пользовательский бэкэнд аутентификации, специально разработанный для конечной точки metrics и разместить его перед другими методами аутентификации.
Запрос всегда сначала проходит через промежуточное ПО, поэтому он всегда будет перенаправлен на /admin/login, а затем пройдет через бэкенд аутентификации.
Какой правильный способ сделать это?
- middleware.py
class LoginRequiredMiddleware(MiddlewareMixin):
def __init__(self, get_response):
self.get_response = get_response
def process_request(self, request):
assert hasattr(request, 'user')
path = request.path_info.lstrip('/')
if path == '' or path == '/':
return self.get_response(request)
url_is_exempt = any(url.match(path) for url in EXEMPT_URLS)
if request.user.is_authenticated or url_is_exempt:
# If the user is authenticated OR the URL is in the exempt list
# go to the requested page
return self.get_response(request)
else:
# Trying to access any page as a non authenticated user
return redirect(f"{settings.LOGIN_URL}?next=/{path}")
- backends.py
class MetricsAuthBackend(BaseBackend):
def authenticate(self, request, username=None, password=None):
if '/metrics' in request.path:
if username == "username":
#need to fix this to use the hash of the password
pwd_valid = check_password(password, "password")
if pwd_valid:
user = User.objects.get(username=username)
return user
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None