Merge pull request #7224 from jumpserver/dev

v2.16.0 rc4
pull/7230/head
Jiangjie.Bai 2021-11-18 17:05:35 +08:00 committed by GitHub
commit d1ccb4af15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 20 deletions

View File

@ -7,7 +7,7 @@ from rest_framework import status
from common.exceptions import JMSException
from .signals import post_auth_failed
from users.utils import LoginBlockUtil, MFABlockUtils
from users.utils import LoginBlockUtil, MFABlockUtils, LoginIpBlockUtil
reason_password_failed = 'password_failed'
reason_password_decrypt_failed = 'password_decrypt_failed'
@ -114,7 +114,18 @@ class AuthFailedError(Exception):
return str(self.msg)
class CredentialError(AuthFailedNeedLogMixin, AuthFailedNeedBlockMixin, AuthFailedError):
class BlockGlobalIpLoginError(AuthFailedError):
error = 'block_global_ip_login'
def __init__(self, username, ip, **kwargs):
self.msg = _("IP is not allowed")
LoginIpBlockUtil(ip).set_block_if_need()
super().__init__(username=username, ip=ip, **kwargs)
class CredentialError(
AuthFailedNeedLogMixin, AuthFailedNeedBlockMixin, BlockGlobalIpLoginError, AuthFailedError
):
def __init__(self, error, username, ip, request):
super().__init__(error=error, username=username, ip=ip, request=request)
util = LoginBlockUtil(username, ip)
@ -177,14 +188,6 @@ class BlockLoginError(AuthFailedNeedBlockMixin, AuthFailedError):
super().__init__(username=username, ip=ip)
class BlockGlobalIpLoginError(AuthFailedError):
error = 'block_global_ip_login'
def __init__(self, username, ip):
self.msg = _("IP is not allowed")
super().__init__(username=username, ip=ip)
class SessionEmptyError(AuthFailedError):
msg = session_empty_msg
error = 'session_empty'

View File

@ -492,6 +492,7 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, MFAMixin, AuthPost
# 标记密码验证成功
self.mark_password_ok(user=user, auto_login=auto_login)
LoginBlockUtil(user.username, ip).clean_failed_count()
LoginIpBlockUtil(ip).clean_block_if_need()
return user
def mark_password_ok(self, user, auto_login=False):
@ -517,6 +518,7 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, MFAMixin, AuthPost
self._check_login_acl(user, ip)
LoginBlockUtil(user.username, ip).clean_failed_count()
LoginIpBlockUtil(ip).clean_block_if_need()
MFABlockUtils(user.username, ip).clean_failed_count()
self.mark_password_ok(user, False)

View File

@ -3353,8 +3353,8 @@ msgid ""
msgstr "单位:分, 当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录"
#: settings/serializers/security.py:61
msgid "IP Black List"
msgstr "IP 黑名单"
msgid "Login IP Black List"
msgstr "登录 IP 黑名单"
#: settings/serializers/security.py:64
msgid ""

View File

@ -58,7 +58,7 @@ class SecurityAuthSerializer(serializers.Serializer):
)
)
SECURITY_LOGIN_IP_BLACK_LIST = serializers.ListField(
default=[], label=_('IP Black List'), allow_empty=True,
default=[], label=_('Login IP Black List'), allow_empty=True,
child=serializers.CharField(max_length=1024, validators=[ip_child_validator]),
help_text=_(
'Format for comma-delimited string. Such as: '

View File

@ -182,21 +182,32 @@ class BlockGlobalIpUtilBase:
self.block_key = self.BLOCK_KEY_TMPL.format(ip)
self.key_ttl = int(settings.SECURITY_LOGIN_LIMIT_TIME) * 60
def sign_limit_key_and_block_key(self):
@property
def ip_in_black_list(self):
return self.ip in settings.SECURITY_LOGIN_IP_BLACK_LIST
def set_block_if_need(self):
if not self.ip_in_black_list:
return
count = cache.get(self.limit_key, 0)
count += 1
cache.set(self.limit_key, count, self.key_ttl)
limit_count = settings.SECURITY_LOGIN_LIMIT_COUNT
if count >= limit_count:
cache.set(self.block_key, True, self.key_ttl)
if count < limit_count:
return
cache.set(self.block_key, True, self.key_ttl)
def clean_block_if_need(self):
if not self.ip_in_black_list:
return
cache.delete(self.limit_key)
cache.delete(self.block_key)
def is_block(self):
if self.ip in settings.SECURITY_LOGIN_IP_BLACK_LIST:
self.sign_limit_key_and_block_key()
return bool(cache.get(self.block_key))
else:
if not self.ip_in_black_list:
return False
return bool(cache.get(self.block_key))
class LoginBlockUtil(BlockUtilBase):