feat(authentication): 超级管理员密码不能是`admin`

pull/4455/head
xinwen 2020-08-05 16:04:05 +08:00 committed by 老广
parent 15fe7f810b
commit a25da8d479
8 changed files with 65 additions and 11 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.shortcuts import redirect
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.generics import CreateAPIView from rest_framework.generics import CreateAPIView
@ -40,3 +40,5 @@ class TokenCreateApi(AuthMixin, CreateAPIView):
return Response(e.as_data(), status=400) return Response(e.as_data(), status=400)
except errors.NeedMoreInfoError as e: except errors.NeedMoreInfoError as e:
return Response(e.as_data(), status=200) return Response(e.as_data(), status=200)
except errors.PasswdTooSimple as e:
return redirect(e.url)

View File

@ -211,3 +211,12 @@ class LoginConfirmOtherError(LoginConfirmBaseError):
class SSOAuthClosed(JMSException): class SSOAuthClosed(JMSException):
default_code = 'sso_auth_closed' default_code = 'sso_auth_closed'
default_detail = _('SSO auth closed') default_detail = _('SSO auth closed')
class PasswdTooSimple(JMSException):
default_code = 'passwd_too_simple'
default_detail = _('Your password is too simple, please change it for security')
def __init__(self, url, *args, **kwargs):
super(PasswdTooSimple, self).__init__(*args, **kwargs)
self.url = url

View File

@ -1,9 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from urllib.parse import urlencode
from functools import partial from functools import partial
import time import time
from django.conf import settings from django.conf import settings
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.shortcuts import reverse
from common.utils import get_object_or_none, get_request_ip, get_logger from common.utils import get_object_or_none, get_request_ip, get_logger
from users.models import User from users.models import User
@ -91,6 +94,8 @@ class AuthMixin:
elif user.password_has_expired: elif user.password_has_expired:
raise CredentialError(error=errors.reason_password_expired) raise CredentialError(error=errors.reason_password_expired)
self._check_passwd_is_too_simple(user, password)
clean_failed_count(username, ip) clean_failed_count(username, ip)
request.session['auth_password'] = 1 request.session['auth_password'] = 1
request.session['user_id'] = str(user.id) request.session['user_id'] = str(user.id)
@ -98,6 +103,22 @@ class AuthMixin:
request.session['auth_backend'] = auth_backend request.session['auth_backend'] = auth_backend
return user return user
@classmethod
def _check_passwd_is_too_simple(cls, user, password):
if user.is_superuser and password == 'admin':
reset_passwd_url = reverse('authentication:reset-password')
query_str = urlencode({
'token': user.generate_reset_token()
})
reset_passwd_url = f'{reset_passwd_url}?{query_str}'
flash_page_url = reverse('authentication:passwd-too-simple-flash-msg')
query_str = urlencode({
'redirect_url': reset_passwd_url
})
raise errors.PasswdTooSimple(f'{flash_page_url}?{query_str}')
def check_user_auth_if_need(self): def check_user_auth_if_need(self):
request = self.request request = self.request
if request.session.get('auth_password') and \ if request.session.get('auth_password') and \

View File

@ -21,6 +21,7 @@ urlpatterns = [
path('password/forgot/sendmail-success/', users_view.UserForgotPasswordSendmailSuccessView.as_view(), path('password/forgot/sendmail-success/', users_view.UserForgotPasswordSendmailSuccessView.as_view(),
name='forgot-password-sendmail-success'), name='forgot-password-sendmail-success'),
path('password/reset/', users_view.UserResetPasswordView.as_view(), name='reset-password'), path('password/reset/', users_view.UserResetPasswordView.as_view(), name='reset-password'),
path('password/too-simple-flash-msg/', views.FlashPasswdTooSimpleMsgView.as_view(), name='passwd-too-simple-flash-msg'),
path('password/reset/success/', users_view.UserResetPasswordSuccessView.as_view(), name='reset-password-success'), path('password/reset/success/', users_view.UserResetPasswordSuccessView.as_view(), name='reset-password-success'),
path('password/verify/', users_view.UserVerifyPasswordView.as_view(), name='user-verify-password'), path('password/verify/', users_view.UserVerifyPasswordView.as_view(), name='user-verify-password'),

View File

@ -29,6 +29,7 @@ from ..forms import get_user_login_form_cls
__all__ = [ __all__ = [
'UserLoginView', 'UserLogoutView', 'UserLoginView', 'UserLogoutView',
'UserLoginGuardView', 'UserLoginWaitConfirmView', 'UserLoginGuardView', 'UserLoginWaitConfirmView',
'FlashPasswdTooSimpleMsgView',
] ]
@ -91,6 +92,8 @@ class UserLoginView(mixins.AuthMixin, FormView):
new_form._errors = form.errors new_form._errors = form.errors
context = self.get_context_data(form=new_form) context = self.get_context_data(form=new_form)
return self.render_to_response(context) return self.render_to_response(context)
except errors.PasswdTooSimple as e:
return redirect(e.url)
return self.redirect_to_guard_view() return self.redirect_to_guard_view()
def redirect_to_guard_view(self): def redirect_to_guard_view(self):
@ -151,6 +154,8 @@ class UserLoginGuardView(mixins.AuthMixin, RedirectView):
return self.format_redirect_url(self.login_confirm_url) return self.format_redirect_url(self.login_confirm_url)
except errors.MFAUnsetError as e: except errors.MFAUnsetError as e:
return e.url return e.url
except errors.PasswdTooSimple as e:
return e.url
else: else:
auth_login(self.request, user) auth_login(self.request, user)
self.send_auth_signal(success=True, user=user) self.send_auth_signal(success=True, user=user)
@ -222,4 +227,16 @@ class UserLogoutView(TemplateView):
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
@method_decorator(never_cache, name='dispatch')
class FlashPasswdTooSimpleMsgView(TemplateView):
template_name = 'flash_message_standalone.html'
def get(self, request, *args, **kwargs):
context = {
'title': _('Please change your password'),
'messages': _('Your password is too simple, please change it for security'),
'interval': 5,
'redirect_url': request.GET.get('redirect_url'),
'auto_redirect': True,
}
return self.render_to_response(context)

View File

@ -2,7 +2,6 @@
# #
import re import re
from django.shortcuts import reverse as dj_reverse from django.shortcuts import reverse as dj_reverse
from django.db.models import Subquery, QuerySet
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-04 15:33+0800\n" "POT-Creation-Date: 2020-08-05 16:43+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n" "Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -1359,11 +1359,11 @@ msgstr "复制成功"
msgid "Welcome back, please enter username and password to login" msgid "Welcome back, please enter username and password to login"
msgstr "欢迎回来,请输入用户名和密码登录" msgstr "欢迎回来,请输入用户名和密码登录"
#: authentication/views/login.py:82 #: authentication/views/login.py:83
msgid "Please enable cookies and try again." msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie" msgstr "设置你的浏览器支持cookie"
#: authentication/views/login.py:178 #: authentication/views/login.py:183
msgid "" msgid ""
"Wait for <b>{}</b> confirm, You also can copy link to her/him <br/>\n" "Wait for <b>{}</b> confirm, You also can copy link to her/him <br/>\n"
" Don't close this page" " Don't close this page"
@ -1371,18 +1371,26 @@ msgstr ""
"等待 <b>{}</b> 确认, 你也可以复制链接发给他/她 <br/>\n" "等待 <b>{}</b> 确认, 你也可以复制链接发给他/她 <br/>\n"
" 不要关闭本页面" " 不要关闭本页面"
#: authentication/views/login.py:183 #: authentication/views/login.py:188
msgid "No ticket found" msgid "No ticket found"
msgstr "没有发现工单" msgstr "没有发现工单"
#: authentication/views/login.py:215 #: authentication/views/login.py:220
msgid "Logout success" msgid "Logout success"
msgstr "退出登录成功" msgstr "退出登录成功"
#: authentication/views/login.py:216 #: authentication/views/login.py:221
msgid "Logout success, return login page" msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面" msgstr "退出登录成功,返回到登录页面"
#: authentication/views/login.py:236
msgid "Please change your password"
msgstr "请修改密码"
#: authentication/views/login.py:237
msgid "Your password is too simple, please change it for security"
msgstr "你的密码过于简单,为了安全,请修改"
#: common/const/__init__.py:6 #: common/const/__init__.py:6
#, python-format #, python-format
msgid "%(name)s was created successfully" msgid "%(name)s was created successfully"
@ -4222,9 +4230,6 @@ msgstr "旗舰版"
#~ msgid "Update asset user auth" #~ msgid "Update asset user auth"
#~ msgstr "更新资产用户认证信息" #~ msgstr "更新资产用户认证信息"
#~ msgid "Please input password"
#~ msgstr "请输入密码"
#~ msgid "Asset user auth" #~ msgid "Asset user auth"
#~ msgstr "资产用户信息" #~ msgstr "资产用户信息"