|
|
|
from django.conf import settings
|
|
|
|
from django.utils.module_loading import import_string
|
|
|
|
from common.utils import get_logger
|
|
|
|
from django.contrib.auth import get_user_model
|
|
|
|
from authentication.signals import user_auth_failed, user_auth_success
|
|
|
|
|
|
|
|
from .base import JMSModelBackend
|
|
|
|
|
|
|
|
logger = get_logger(__file__)
|
|
|
|
|
|
|
|
custom_authenticate_method = None
|
|
|
|
|
|
|
|
if settings.AUTH_CUSTOM:
|
|
|
|
""" 保证自定义认证方法在服务运行时不能被更改,只在第一次调用时加载一次 """
|
|
|
|
try:
|
|
|
|
custom_auth_method_path = 'data.auth.main.authenticate'
|
|
|
|
custom_authenticate_method = import_string(custom_auth_method_path)
|
|
|
|
except Exception as e:
|
|
|
|
logger.warning('Import custom auth method failed: {}, Maybe not enabled'.format(e))
|
|
|
|
|
|
|
|
|
|
|
|
class CustomAuthBackend(JMSModelBackend):
|
|
|
|
|
|
|
|
def is_enabled(self):
|
|
|
|
return settings.AUTH_CUSTOM and callable(custom_authenticate_method)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_or_create_user_from_userinfo(userinfo: dict):
|
|
|
|
username = userinfo['username']
|
|
|
|
attrs = ['name', 'username', 'email', 'is_active']
|
|
|
|
defaults = {attr: userinfo[attr] for attr in attrs}
|
|
|
|
user, created = get_user_model().objects.get_or_create(
|
|
|
|
username=username, defaults=defaults
|
|
|
|
)
|
|
|
|
return user, created
|
|
|
|
|
|
|
|
def authenticate(self, request, username=None, password=None, **kwargs):
|
|
|
|
try:
|
|
|
|
userinfo: dict = custom_authenticate_method(
|
|
|
|
username=username, password=password, **kwargs
|
|
|
|
)
|
|
|
|
user, created = self.get_or_create_user_from_userinfo(userinfo)
|
|
|
|
except Exception as e:
|
|
|
|
logger.error('Custom authenticate error: {}'.format(e))
|
|
|
|
return None
|
|
|
|
|
|
|
|
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
|