mirror of
https://github.com/jumpserver/jumpserver.git
synced 2026-03-18 11:02:09 +00:00
fix: make OTP option always selectable in MFA selection
page
This commit is contained in:
@@ -12,6 +12,10 @@ class MFAOtp(BaseMFA):
|
||||
display_name = MFAType.OTP.name
|
||||
placeholder = _('OTP verification code')
|
||||
|
||||
def is_configured(self):
|
||||
"""检查 OTP 是否已配置"""
|
||||
return bool(self.user.otp_secret_key) if self.is_authenticated() else False
|
||||
|
||||
def _check_code(self, code):
|
||||
from users.utils import check_otp_code
|
||||
assert self.is_authenticated()
|
||||
|
||||
@@ -15,6 +15,14 @@
|
||||
<div class="form-group">
|
||||
{% include '_mfa_login_field.html' %}
|
||||
</div>
|
||||
|
||||
{% if show_otp_hint %}
|
||||
<div id="otp-setup-hint" class="alert alert-info" style="display: none; margin-top: 10px; font-size: 13px;">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
{% trans "To set up OTP, leave the field empty and click Next. You'll be guided to the setup page." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<button id='submit_button' type="submit" class="btn btn-primary block full-width m-b">
|
||||
{% trans 'Next' %}
|
||||
</button>
|
||||
@@ -27,4 +35,28 @@
|
||||
margin-top: 15px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
// 当选择 OTP 时显示提示信息
|
||||
{% if show_otp_hint %}
|
||||
$(document).ready(function() {
|
||||
const originalSelectChange = window.selectChange;
|
||||
window.selectChange = function(name, onLoad) {
|
||||
originalSelectChange(name, onLoad);
|
||||
|
||||
// 如果选择了 OTP,显示提示
|
||||
if (name === 'otp') {
|
||||
$('#otp-setup-hint').slideDown(200);
|
||||
} else {
|
||||
$('#otp-setup-hint').slideUp(200);
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载时检查默认选中的 MFA 类型
|
||||
const defaultMfaType = $('#mfa-select').val();
|
||||
if (defaultMfaType === 'otp') {
|
||||
$('#otp-setup-hint').show();
|
||||
}
|
||||
});
|
||||
{% endif %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -42,6 +42,16 @@ class UserLoginMFAView(mixins.AuthMixin, FormView):
|
||||
return redirect(reverse('authentication:login-face-capture'))
|
||||
elif mfa_type == MFAType.Passkey:
|
||||
return redirect('/api/v1/authentication/passkeys/login/')
|
||||
|
||||
# 特殊处理:如果选择 OTP 且未配置,直接跳转到设置页面
|
||||
if mfa_type == 'otp':
|
||||
user = self.get_user_from_session()
|
||||
mfa_backend = user.get_mfa_backend_by_type(mfa_type)
|
||||
if mfa_backend and hasattr(mfa_backend, 'is_configured'):
|
||||
if not mfa_backend.is_configured():
|
||||
set_url = mfa_backend.get_enable_url()
|
||||
return redirect(set_url + '?_=login_mfa')
|
||||
|
||||
return self.do_mfa_check(form, code, mfa_type)
|
||||
|
||||
def do_mfa_check(self, form, code, mfa_type):
|
||||
@@ -67,7 +77,24 @@ class UserLoginMFAView(mixins.AuthMixin, FormView):
|
||||
def get_context_data(self, **kwargs):
|
||||
user = self.get_user_from_session()
|
||||
mfa_context = self.get_user_mfa_context(user)
|
||||
|
||||
# 检查是否需要显示 OTP 设置提示
|
||||
# 只有在有多个 MFA 选项且 OTP 未配置时才显示
|
||||
mfa_backends = mfa_context.get('mfa_backends', [])
|
||||
show_otp_hint = False
|
||||
|
||||
if len(mfa_backends) > 1: # 有多个 MFA 选项
|
||||
for backend in mfa_backends:
|
||||
if backend.name == 'otp':
|
||||
if hasattr(backend, 'is_configured'):
|
||||
show_otp_hint = not backend.is_configured()
|
||||
else:
|
||||
show_otp_hint = not backend.is_active()
|
||||
break
|
||||
|
||||
kwargs.update(mfa_context)
|
||||
kwargs['show_otp_hint'] = show_otp_hint
|
||||
return kwargs
|
||||
return kwargs
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
>
|
||||
{% for backend in mfa_backends %}
|
||||
<option value="{{ backend.name }}"
|
||||
{% if not backend.is_active %} disabled {% endif %}
|
||||
{% if backend.name != 'otp' and not backend.is_active %} disabled {% endif %}
|
||||
>
|
||||
{{ backend.display_name }}
|
||||
</option>
|
||||
|
||||
Reference in New Issue
Block a user