[Update] 修改确认用户认证成功和绑定MFA的前后逻辑(解决绕过绑定MFA的漏洞;解决管理员重置用户MFA后自动退出的问题)

pull/3588/head
BaiJiangJie 2020-01-03 15:26:38 +08:00
parent 352bfeeb7a
commit b072e98148
5 changed files with 35 additions and 20 deletions

View File

@ -6,7 +6,7 @@ from django.conf import settings
from common.utils import get_object_or_none, get_request_ip, get_logger
from users.models import User
from users.utils import (
is_block_login, clean_failed_count, increase_login_failed_count
is_block_login, clean_failed_count, increase_login_failed_count,
)
from . import errors
from .utils import check_user_valid

View File

@ -20,7 +20,7 @@ from django.urls import reverse_lazy
from common.utils import get_request_ip, get_object_or_none
from users.utils import (
redirect_user_first_login_or_index
redirect_user_first_login_or_index, set_tmp_user_to_cache
)
from .. import forms, mixins, errors
@ -128,13 +128,14 @@ class UserLoginGuardView(mixins.AuthMixin, RedirectView):
except errors.LoginConfirmBaseError:
return self.format_redirect_url(self.login_confirm_url)
else:
auth_login(self.request, user)
self.send_auth_signal(success=True, user=user)
self.clear_auth_mark()
# 启用但是没有设置otp, 排除radius
if user.mfa_enabled_but_not_set():
# 1,2,mfa_setting & F
set_tmp_user_to_cache(self.request, user)
return reverse('users:user-otp-enable-authentication')
auth_login(self.request, user)
self.send_auth_signal(success=True, user=user)
self.clear_auth_mark()
url = redirect_user_first_login_or_index(
self.request, self.redirect_field_name
)

View File

@ -179,5 +179,4 @@ class UserResetOTPApi(UserQuerysetMixin, generics.RetrieveAPIView):
if user.mfa_enabled:
user.reset_mfa()
user.save()
logout(request)
return Response({"msg": "success"})

View File

@ -215,6 +215,12 @@ def set_tmp_user_to_cache(request, user, ttl=3600):
cache.set(request.session.session_key+'user', user, ttl)
def delete_tmp_user_for_cache(request):
if not request.session.session_key:
return None
cache.delete(request.session.session_key+'user')
def redirect_user_first_login_or_index(request, redirect_field_name):
if request.user.is_first_login:
return reverse('users:user-first-login')

View File

@ -24,8 +24,10 @@ from common.permissions import (
)
from .. import forms
from ..models import User
from ..utils import generate_otp_uri, check_otp_code, \
get_user_or_tmp_user, get_password_check_rules, check_password_rules
from ..utils import (
generate_otp_uri, check_otp_code, get_user_or_tmp_user,
delete_tmp_user_for_cache, check_password_rules, get_password_check_rules,
)
__all__ = [
'UserProfileView',
@ -163,6 +165,13 @@ class UserCheckPasswordView(FormView):
success_url = reverse('users:user-otp-enable-install-app')
return success_url
def get_context_data(self, **kwargs):
context = {
'user': get_user_or_tmp_user(self.request)
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class UserOtpEnableInstallAppView(TemplateView):
template_name = 'users/user_otp_enable_install_app.html'
@ -181,17 +190,6 @@ class UserOtpEnableBindView(TemplateView, FormView):
form_class = forms.UserCheckOtpCodeForm
success_url = reverse_lazy('users:user-otp-settings-success')
def get_context_data(self, **kwargs):
user = get_user_or_tmp_user(self.request)
otp_uri, otp_secret_key = generate_otp_uri(self.request)
context = {
'otp_uri': otp_uri,
'otp_secret_key': otp_secret_key,
'user': user
}
kwargs.update(context)
return super().get_context_data(**kwargs)
def form_valid(self, form):
otp_code = form.cleaned_data.get('otp_code')
otp_secret_key = cache.get(self.request.session.session_key+'otp_key', '')
@ -210,6 +208,17 @@ class UserOtpEnableBindView(TemplateView, FormView):
user.otp_secret_key = otp_secret_key
user.save()
def get_context_data(self, **kwargs):
user = get_user_or_tmp_user(self.request)
otp_uri, otp_secret_key = generate_otp_uri(self.request)
context = {
'otp_uri': otp_uri,
'otp_secret_key': otp_secret_key,
'user': user
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class UserDisableMFAView(FormView):
template_name = 'users/user_disable_mfa.html'
@ -258,6 +267,6 @@ class UserOtpSettingsSuccessView(TemplateView):
if not user.mfa_enabled:
title = _('MFA disable success')
describe = _('MFA disable success, return login page')
delete_tmp_user_for_cache(self.request)
return title, describe