From ff9b1a887fe914defd9db127cd1392c090c50e4a Mon Sep 17 00:00:00 2001 From: BaiJiangJie Date: Wed, 4 Jul 2018 16:55:11 +0800 Subject: [PATCH] =?UTF-8?q?[Update]=20=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=A4=B1=E8=B4=A5=E6=AC=A1=E6=95=B0=E9=99=90?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/i18n/zh/LC_MESSAGES/django.mo | Bin 36216 -> 36297 bytes apps/i18n/zh/LC_MESSAGES/django.po | 44 ++++++++++++++------------ apps/users/templates/users/login.html | 6 +++- apps/users/views/login.py | 31 +++++++++++++----- 4 files changed, 52 insertions(+), 29 deletions(-) diff --git a/apps/i18n/zh/LC_MESSAGES/django.mo b/apps/i18n/zh/LC_MESSAGES/django.mo index 339af4456cb72a4e21841737e7c98bce3a39fc6a..b5474cbe1cdec6a6fb164cf841611e659e75bd94 100644 GIT binary patch delta 11843 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 delta 11771 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 V4I4LTwEf6{bJ6V6y-K diff --git a/apps/i18n/zh/LC_MESSAGES/django.po b/apps/i18n/zh/LC_MESSAGES/django.po index 4396c01fb..56fabe11a 100644 --- a/apps/i18n/zh/LC_MESSAGES/django.po +++ b/apps/i18n/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Jumpserver 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-07-03 16:48+0800\n" +"POT-Creation-Date: 2018-07-04 16:46+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -156,7 +156,7 @@ msgstr "名称" #: perms/templates/perms/asset_permission_user.html:55 users/forms.py:13 #: users/forms.py:31 users/models/authentication.py:70 users/models/user.py:47 #: users/templates/users/_select_user_modal.html:14 -#: users/templates/users/login.html:56 +#: users/templates/users/login.html:60 #: users/templates/users/login_log_list.html:49 #: users/templates/users/user_detail.html:67 #: users/templates/users/user_list.html:24 @@ -170,7 +170,7 @@ msgstr "密码或密钥密码" #: assets/forms/user.py:25 assets/models/base.py:23 common/forms.py:113 #: users/forms.py:15 users/forms.py:33 users/forms.py:45 -#: users/templates/users/login.html:59 +#: users/templates/users/login.html:63 #: users/templates/users/reset_password.html:53 #: users/templates/users/user_create.html:10 #: users/templates/users/user_password_authentication.html:14 @@ -2006,7 +2006,7 @@ msgid "Logout" msgstr "注销登录" #: templates/_header_bar.html:49 users/templates/users/login.html:44 -#: users/templates/users/login.html:64 +#: users/templates/users/login.html:68 msgid "Login" msgstr "登录" @@ -2046,7 +2046,7 @@ msgstr "关闭" #: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44 #: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95 -#: users/views/login.py:311 users/views/login.py:369 users/views/user.py:65 +#: users/views/login.py:330 users/views/login.py:388 users/views/user.py:65 #: users/views/user.py:80 users/views/user.py:102 users/views/user.py:175 #: users/views/user.py:330 users/views/user.py:380 users/views/user.py:415 msgid "Users" @@ -2641,7 +2641,7 @@ msgid " for more information" msgstr "获取更多信息" #: users/templates/users/forgot_password.html:26 -#: users/templates/users/login.html:73 +#: users/templates/users/login.html:77 msgid "Forgot password" msgstr "忘记密码" @@ -2650,6 +2650,10 @@ msgid "Input your email, that will send a mail to your" msgstr "输入您的邮箱, 将会发一封重置邮件到您的邮箱中" #: users/templates/users/login.html:50 +msgid "Log in frequently and try again later" +msgstr "登录频繁, 稍后重试" + +#: users/templates/users/login.html:53 msgid "Captcha invalid" msgstr "验证码错误" @@ -3045,60 +3049,60 @@ msgstr "更新用户组" msgid "User group granted asset" msgstr "用户组授权资产" -#: users/views/login.py:63 +#: users/views/login.py:74 msgid "Please enable cookies and try again." msgstr "设置你的浏览器支持cookie" -#: users/views/login.py:159 users/views/user.py:500 users/views/user.py:525 +#: users/views/login.py:178 users/views/user.py:500 users/views/user.py:525 msgid "MFA code invalid" msgstr "MFA码认证失败" -#: users/views/login.py:188 +#: users/views/login.py:207 msgid "Logout success" msgstr "退出登录成功" -#: users/views/login.py:189 +#: users/views/login.py:208 msgid "Logout success, return login page" msgstr "退出登录成功,返回到登录页面" -#: users/views/login.py:205 +#: users/views/login.py:224 msgid "Email address invalid, please input again" msgstr "邮箱地址错误,重新输入" -#: users/views/login.py:218 +#: users/views/login.py:237 msgid "Send reset password message" msgstr "发送重置密码邮件" -#: users/views/login.py:219 +#: users/views/login.py:238 msgid "Send reset password mail success, login your mail box and follow it " msgstr "" "发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)" -#: users/views/login.py:232 +#: users/views/login.py:251 msgid "Reset password success" msgstr "重置密码成功" -#: users/views/login.py:233 +#: users/views/login.py:252 msgid "Reset password success, return to login page" msgstr "重置密码成功,返回到登录页面" -#: users/views/login.py:254 users/views/login.py:267 +#: users/views/login.py:273 users/views/login.py:286 msgid "Token invalid or expired" msgstr "Token错误或失效" -#: users/views/login.py:263 +#: users/views/login.py:282 msgid "Password not same" msgstr "密码不一致" -#: users/views/login.py:273 users/views/user.py:118 users/views/user.py:398 +#: users/views/login.py:292 users/views/user.py:118 users/views/user.py:398 msgid "* Your password does not meet the requirements" msgstr "* 您的密码不符合要求" -#: users/views/login.py:311 +#: users/views/login.py:330 msgid "First login" msgstr "首次登陆" -#: users/views/login.py:370 +#: users/views/login.py:389 msgid "Login log list" msgstr "登录日志" diff --git a/apps/users/templates/users/login.html b/apps/users/templates/users/login.html index 7dd3f5d0a..7ea824502 100644 --- a/apps/users/templates/users/login.html +++ b/apps/users/templates/users/login.html @@ -45,13 +45,17 @@
{% csrf_token %} - {% if form.errors %} + + {% if login_limit %} +

{% trans 'Log in frequently and try again later' %}

+ {% elif form.errors %} {% if 'captcha' in form.errors %}

{% trans 'Captcha invalid' %}

{% else %}

{{ form.non_field_errors.as_text }}

{% endif %} {% endif %} +
diff --git a/apps/users/views/login.py b/apps/users/views/login.py index 7e853e45f..f58ef7b8f 100644 --- a/apps/users/views/login.py +++ b/apps/users/views/login.py @@ -48,7 +48,8 @@ class UserLoginView(FormView): form_class = forms.UserLoginForm form_class_captcha = forms.UserLoginCaptchaForm redirect_field_name = 'next' - key_prefix = "_LOGIN_INVALID_{}" + key_prefix_captcha = "_LOGIN_INVALID_{}" + key_prefix_limit = "_LOGIN_LIMIT_{}_{}" def get(self, request, *args, **kwargs): if request.user.is_staff: @@ -58,6 +59,16 @@ class UserLoginView(FormView): request.session.set_test_cookie() return super().get(request, *args, **kwargs) + def post(self, request, *args, **kwargs): + # limit login authentication + ip = get_login_ip(request) + username = self.request.POST.get('username') + count = cache.get(self.key_prefix_limit.format(ip, username)) + if count and count >= 3: + return self.render_to_response(self.get_context_data(login_limit=True)) + + return super().post(request, *args, **kwargs) + def form_valid(self, form): if not self.request.session.test_cookie_worked(): return HttpResponse(_("Please enable cookies and try again.")) @@ -66,17 +77,24 @@ class UserLoginView(FormView): return redirect(self.get_success_url()) def form_invalid(self, form): - # Write login failed log + # write login failed log + username = form.cleaned_data.get('username') data = { - 'username': form.cleaned_data.get('username'), + 'username': username, 'mfa': LoginLog.MFA_UNKNOWN, 'reason': LoginLog.REASON_PASSWORD, 'status': False } self.write_login_log(data) + # limit user login failed times ip = get_login_ip(self.request) - cache.set(self.key_prefix.format(ip), 1, 3600) + key_limit = self.key_prefix_limit.format(ip, username) + count = cache.get(key_limit) + count = count + 1 if count else 1 + cache.set(key_limit, count, 1800) + + cache.set(self.key_prefix_captcha.format(ip), 1, 3600) old_form = form form = self.form_class_captcha(data=form.data) form._errors = old_form.errors @@ -84,7 +102,7 @@ class UserLoginView(FormView): def get_form_class(self): ip = get_login_ip(self.request) - if cache.get(self.key_prefix.format(ip)): + if cache.get(self.key_prefix_captcha.format(ip)): return self.form_class_captcha else: return self.form_class @@ -101,7 +119,6 @@ class UserLoginView(FormView): elif not user.otp_enabled: # 0 & T,F auth_login(self.request, user) - # Write login success log data = { 'username': self.request.user.username, 'mfa': int(self.request.user.otp_enabled), @@ -142,7 +159,6 @@ class UserLoginOtpView(FormView): if check_otp_code(otp_secret_key, otp_code): auth_login(self.request, user) - # Write login success log data = { 'username': self.request.user.username, 'mfa': int(self.request.user.otp_enabled), @@ -152,7 +168,6 @@ class UserLoginOtpView(FormView): self.write_login_log(data) return redirect(self.get_success_url()) else: - # Write login failed log data = { 'username': user.username, 'mfa': int(user.otp_enabled),