fix: many login logs are record when user login once

This commit is contained in:
Bai
2026-04-28 10:43:12 +08:00
committed by 老广
parent 2c67e71cfb
commit 48021bea50
10 changed files with 48 additions and 90 deletions

View File

@@ -3,6 +3,8 @@ from django.contrib.auth.backends import ModelBackend
from common.utils import get_logger
from users.models import User
from authentication.signals import backend_auth_failed
from authentication.errors import reason_choices, reason_user_invalid
UserModel = get_user_model()
logger = get_logger(__file__)
@@ -65,3 +67,14 @@ class JMSBaseAuthBackend:
class JMSModelBackend(JMSBaseAuthBackend, ModelBackend):
def user_can_authenticate(self, user):
return True
class RedirectAuthBackend(JMSBaseAuthBackend):
backend = None
def send_backend_auth_failed_signal(self, request, username=None, reason=None):
default_reason = reason_choices.get(reason_user_invalid, reason)
backend_auth_failed.send(
sender=self.__class__, username=username, request=request,
reason=default_reason, backend=self.backend
)

View File

@@ -5,13 +5,15 @@ from django.conf import settings
from django_cas_ng.backends import CASBackend as _CASBackend
from common.utils import get_logger
from ..base import JMSBaseAuthBackend
from ..base import RedirectAuthBackend
__all__ = ['CASBackend']
logger = get_logger(__name__)
class CASBackend(JMSBaseAuthBackend, _CASBackend):
class CASBackend(RedirectAuthBackend, _CASBackend):
backend = settings.AUTH_BACKEND_CAS
@staticmethod
def is_enabled():
return settings.AUTH_CAS
@@ -19,4 +21,7 @@ class CASBackend(JMSBaseAuthBackend, _CASBackend):
def authenticate(self, request, ticket, service):
# 这里做个hack ,让父类始终走CAS_CREATE_USER=True的逻辑然后调用 authentication/mixins.py 中的 custom_get_or_create 方法
settings.CAS_CREATE_USER = True
return super().authenticate(request, ticket, service)
user = super().authenticate(request, ticket, service)
if user is None:
self.send_backend_auth_failed_signal(request=request)
return user

View File

@@ -3,7 +3,6 @@ from django.contrib.auth import get_user_model
from django.utils.module_loading import import_string
from django.utils.translation import gettext_lazy as _
from authentication.signals import user_auth_failed, user_auth_success
from common.utils import get_logger
from .base import JMSBaseAuthBackend
@@ -48,16 +47,7 @@ class CustomAuthBackend(JMSBaseAuthBackend):
if self.user_can_authenticate(user):
logger.info(f'Custom authenticate success: {user.username}')
user_auth_success.send(
sender=self.__class__, request=request, user=user,
backend=settings.AUTH_BACKEND_CUSTOM
)
return user
else:
logger.info(f'Custom authenticate failed: {user.username}')
user_auth_failed.send(
sender=self.__class__, request=request, username=user.username,
reason=_('User invalid, disabled or expired'),
backend=settings.AUTH_BACKEND_CUSTOM
)
return None

View File

@@ -12,13 +12,12 @@ from django.urls import reverse
from common.utils import get_logger
from users.utils import construct_user_email
from authentication.utils import build_absolute_uri
from authentication.signals import user_auth_failed, user_auth_success
from common.exceptions import JMSException
from .signals import (
oauth2_create_or_update_user
)
from ..base import JMSBaseAuthBackend
from ..base import RedirectAuthBackend
__all__ = ['OAuth2Backend']
@@ -26,7 +25,9 @@ __all__ = ['OAuth2Backend']
logger = get_logger(__name__)
class OAuth2Backend(JMSBaseAuthBackend):
class OAuth2Backend(RedirectAuthBackend):
backend = settings.AUTH_BACKEND_OAUTH2
@staticmethod
def is_enabled():
return settings.AUTH_OAUTH2
@@ -144,18 +145,9 @@ class OAuth2Backend(JMSBaseAuthBackend):
if self.user_can_authenticate(user):
logger.debug(log_prompt.format('OAuth2 user login success'))
logger.debug(log_prompt.format('Send signal => oauth2 user login success'))
user_auth_success.send(
sender=self.__class__, request=request, user=user,
backend=settings.AUTH_BACKEND_OAUTH2
)
return user
else:
logger.debug(log_prompt.format('OAuth2 user login failed'))
logger.debug(log_prompt.format('Send signal => oauth2 user login failed'))
user_auth_failed.send(
sender=self.__class__, request=request, username=user.username,
reason=_('User invalid, disabled or expired'),
backend=settings.AUTH_BACKEND_OAUTH2
)
self.send_backend_auth_failed_signal(request=request, username=user.username)
return None

View File

@@ -16,7 +16,6 @@ from django.contrib.auth.backends import ModelBackend
from django.db import transaction
from django.urls import reverse
from authentication.signals import user_auth_success, user_auth_failed
from authentication.utils import build_absolute_uri_for_oidc
from common.utils import get_logger
from users.utils import construct_user_email
@@ -25,7 +24,7 @@ from .signals import (
openid_create_or_update_user
)
from .utils import validate_and_return_id_token
from ..base import JMSBaseAuthBackend
from ..base import RedirectAuthBackend, JMSBaseAuthBackend
logger = get_logger(__file__)
@@ -66,14 +65,14 @@ class UserMixin:
return user, created
class OIDCBaseBackend(UserMixin, JMSBaseAuthBackend, ModelBackend):
class OIDCBaseBackend(UserMixin, ModelBackend):
@staticmethod
def is_enabled():
return settings.AUTH_OPENID
class OIDCAuthCodeBackend(OIDCBaseBackend):
class OIDCAuthCodeBackend(RedirectAuthBackend, OIDCBaseBackend):
""" Allows to authenticate users using an OpenID Connect Provider (OP).
This authentication backend is able to authenticate users in the case of the OpenID Connect
@@ -84,6 +83,8 @@ class OIDCAuthCodeBackend(OIDCBaseBackend):
"""
backend = settings.AUTH_BACKEND_OIDC_CODE
@ssl_verification
def authenticate(self, request, nonce=None, code_verifier=None):
""" Authenticates users in case of the OpenID Connect Authorization code flow. """
@@ -212,23 +213,15 @@ class OIDCAuthCodeBackend(OIDCBaseBackend):
if self.user_can_authenticate(user):
logger.debug(log_prompt.format('OpenID user login success'))
logger.debug(log_prompt.format('Send signal => openid user login success'))
user_auth_success.send(
sender=self.__class__, request=request, user=user,
backend=settings.AUTH_BACKEND_OIDC_CODE
)
return user
else:
logger.debug(log_prompt.format('OpenID user login failed'))
logger.debug(log_prompt.format('Send signal => openid user login failed'))
user_auth_failed.send(
sender=self.__class__, request=request, username=user.username,
reason="User is invalid", backend=settings.AUTH_BACKEND_OIDC_CODE
)
self.send_backend_auth_failed_signal(request=request, username=user.username)
return None
class OIDCAuthPasswordBackend(OIDCBaseBackend):
class OIDCAuthPasswordBackend(JMSBaseAuthBackend, OIDCBaseBackend):
@ssl_verification
def authenticate(self, request, username=None, password=None):
@@ -274,11 +267,6 @@ class OIDCAuthPasswordBackend(OIDCBaseBackend):
error = "Json token response error, token response " \
"content is: {}, error is: {}".format(token_response.content, str(e))
logger.debug(log_prompt.format(error))
logger.debug(log_prompt.format('Send signal => openid user login failed'))
user_auth_failed.send(
sender=self.__class__, request=request, username=username, reason=error,
backend=settings.AUTH_BACKEND_OIDC_PASSWORD
)
return
# Retrieves the access token
@@ -303,11 +291,6 @@ class OIDCAuthPasswordBackend(OIDCBaseBackend):
error = "Json claims response error, claims response " \
"content is: {}, error is: {}".format(claims_response.content, str(e))
logger.debug(log_prompt.format(error))
logger.debug(log_prompt.format('Send signal => openid user login failed'))
user_auth_failed.send(
sender=self.__class__, request=request, username=username, reason=error,
backend=settings.AUTH_BACKEND_OIDC_PASSWORD
)
return
logger.debug(log_prompt.format('Get or create user from claims'))
@@ -317,17 +300,7 @@ class OIDCAuthPasswordBackend(OIDCBaseBackend):
if self.user_can_authenticate(user):
logger.debug(log_prompt.format('OpenID user login success'))
logger.debug(log_prompt.format('Send signal => openid user login success'))
user_auth_success.send(
sender=self.__class__, request=request, user=user,
backend=settings.AUTH_BACKEND_OIDC_PASSWORD
)
return user
else:
logger.debug(log_prompt.format('OpenID user login failed'))
logger.debug(log_prompt.format('Send signal => openid user login failed'))
user_auth_failed.send(
sender=self.__class__, request=request, username=username, reason="User is invalid",
backend=settings.AUTH_BACKEND_OIDC_PASSWORD
)
return None

View File

@@ -5,19 +5,19 @@ from django.conf import settings
from django.db import transaction
from common.utils import get_logger
from authentication.errors import reason_choices, reason_user_invalid
from .signals import (
saml2_create_or_update_user
)
from authentication.signals import user_auth_failed, user_auth_success
from ..base import JMSBaseAuthBackend
from ..base import RedirectAuthBackend
__all__ = ['SAML2Backend']
logger = get_logger(__name__)
class SAML2Backend(JMSBaseAuthBackend):
class SAML2Backend(RedirectAuthBackend):
backend = settings.AUTH_BACKEND_SAML2
@staticmethod
def is_enabled():
return settings.AUTH_SAML2
@@ -59,16 +59,8 @@ class SAML2Backend(JMSBaseAuthBackend):
if self.user_can_authenticate(user):
logger.debug(log_prompt.format('SAML2 user login success'))
user_auth_success.send(
sender=self.__class__, request=request, user=user, created=created,
backend=settings.AUTH_BACKEND_SAML2
)
return user
else:
logger.debug(log_prompt.format('SAML2 user login failed'))
user_auth_failed.send(
sender=self.__class__, request=request, username=username,
reason=reason_choices.get(reason_user_invalid),
backend=settings.AUTH_BACKEND_SAML2
)
self.send_backend_auth_failed_signal(request=request, username=user.username)
return None

View File

@@ -10,7 +10,7 @@ from django.utils.translation import gettext as _
from apps.authentication import mixins
from audits.signal_handlers import send_login_info_to_reviewers
from authentication.signals import post_auth_failed
from authentication.signals import post_auth_failed, post_auth_success
from common.utils import gen_key_pair, gen_gm_key_pair
from common.utils import get_request_ip
@@ -101,6 +101,9 @@ class ThirdPartyLoginMiddleware(mixins.AuthMixin):
response = render(request, 'authentication/auth_fail_flash_message_standalone.html', context)
else:
if not self.request.session.get('auth_confirm_required'):
post_auth_success.send(
sender=self.__class__, user=request.user, request=self.request
)
return response
guard_url = reverse('authentication:login-guard')
args = request.META.get('QUERY_STRING', '')

View File

@@ -177,6 +177,9 @@ def authenticate(request=None, **credentials):
if user is None:
continue
if request:
request.session['auth_backend'] = backend_path
if not user.is_valid:
temp_user = user
temp_user.backend = backend_path

View File

@@ -7,7 +7,7 @@ from django_cas_ng.signals import cas_user_authenticated
from apps.jumpserver.settings.auth import AUTHENTICATION_BACKENDS_THIRD_PARTY
from audits.models import UserSession
from common.sessions.cache import user_session_manager
from .signals import post_auth_success, post_auth_failed, user_auth_failed, user_auth_success
from .signals import post_auth_failed, backend_auth_failed
from .backends.oauth2_provider.signal_handlers import *
@@ -43,19 +43,7 @@ def on_user_auth_login_success(sender, user, request, **kwargs):
user.lang = lang
@receiver(cas_user_authenticated)
def on_cas_user_login_success(sender, request, user, **kwargs):
request.session['auth_backend'] = settings.AUTH_BACKEND_CAS
post_auth_success.send(sender, user=user, request=request)
@receiver(user_auth_success)
def on_user_login_success(sender, request, user, backend, create=False, **kwargs):
request.session['auth_backend'] = backend
post_auth_success.send(sender, user=user, request=request)
@receiver(user_auth_failed)
@receiver(backend_auth_failed)
def on_user_login_failed(sender, username, request, reason, backend, **kwargs):
request.session['auth_backend'] = backend
post_auth_failed.send(sender, username=username, request=request, reason=reason)

View File

@@ -3,5 +3,4 @@ from django.dispatch import Signal
post_auth_success = Signal()
post_auth_failed = Signal()
user_auth_success = Signal()
user_auth_failed = Signal()
backend_auth_failed = Signal()