feat: 自定义MFA认证逻辑 (#8891)

* feat: 自定义MFA认证

* feat: 修改翻译信息

Co-authored-by: halo <wuyihuangw@gmail.com>
Co-authored-by: Jiangjie.Bai <bugatti_it@163.com>
This commit is contained in:
fit2bot
2022-11-04 14:29:15 +08:00
committed by GitHub
parent 2029e9f8df
commit 13ae50f5d0
10 changed files with 181 additions and 93 deletions

View File

@@ -2,7 +2,7 @@ from django.db.models import TextChoices
from authentication.confirm import CONFIRM_BACKENDS
from .confirm import ConfirmMFA, ConfirmPassword, ConfirmReLogin
from .mfa import MFAOtp, MFASms, MFARadius
from .mfa import MFAOtp, MFASms, MFARadius, MFACustom
RSA_PRIVATE_KEY = 'rsa_private_key'
RSA_PUBLIC_KEY = 'rsa_public_key'
@@ -35,3 +35,4 @@ class MFAType(TextChoices):
OTP = MFAOtp.name, MFAOtp.display_name
SMS = MFASms.name, MFASms.display_name
Radius = MFARadius.name, MFARadius.display_name
Custom = MFACustom.name, MFACustom.display_name

View File

@@ -1,5 +1,4 @@
from .otp import MFAOtp, otp_failed_msg
from .sms import MFASms
from .radius import MFARadius
MFA_BACKENDS = [MFAOtp, MFASms, MFARadius]
from .custom import MFACustom

View File

@@ -0,0 +1,59 @@
from django.conf import settings
from django.utils.module_loading import import_string
from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger
from .base import BaseMFA
logger = get_logger(__file__)
mfa_custom_method = None
if settings.MFA_CUSTOM:
""" 保证自定义认证方法在服务运行时不能被更改,只在第一次调用时加载一次 """
try:
mfa_custom_method_path = 'data.mfa.main.check_code'
mfa_custom_method = import_string(mfa_custom_method_path)
except Exception as e:
logger.warning('Import custom auth method failed: {}, Maybe not enabled'.format(e))
custom_failed_msg = _("MFA Custom code invalid")
class MFACustom(BaseMFA):
name = 'mfa_custom'
display_name = 'Custom'
placeholder = _("MFA custom verification code")
def check_code(self, code):
assert self.is_authenticated()
ok = False
try:
ok = mfa_custom_method(user=self.user, code=code)
except Exception as exc:
logger.error('Custom authenticate error: {}'.format(exc))
msg = '' if ok else custom_failed_msg
return ok, msg
def is_active(self):
return True
@staticmethod
def global_enabled():
return settings.MFA_CUSTOM and callable(mfa_custom_method)
def get_enable_url(self) -> str:
return ''
def can_disable(self):
return False
def disable(self):
return ''
@staticmethod
def help_text_of_disable():
return _("MFA custom global enabled, cannot disable")
def get_disable_url(self) -> str:
return ''