perf: 优化ip黑白名单

pull/7246/head
feng626 2021-11-18 22:20:35 +08:00 committed by 老广
parent d94c515cfc
commit 24d0d52a0a
6 changed files with 141 additions and 83 deletions

View File

@ -51,10 +51,14 @@ invalid_login_msg = _(
"You can also try {times_try} times " "You can also try {times_try} times "
"(The account will be temporarily locked for {block_time} minutes)" "(The account will be temporarily locked for {block_time} minutes)"
) )
block_login_msg = _( block_user_login_msg = _(
"The account has been locked " "The account has been locked "
"(please contact admin to unlock it or try again after {} minutes)" "(please contact admin to unlock it or try again after {} minutes)"
) )
block_ip_login_msg = _(
"The ip has been locked "
"(please contact admin to unlock it or try again after {} minutes)"
)
block_mfa_msg = _( block_mfa_msg = _(
"The account has been locked " "The account has been locked "
"(please contact admin to unlock it or try again after {} minutes)" "(please contact admin to unlock it or try again after {} minutes)"
@ -118,7 +122,7 @@ class BlockGlobalIpLoginError(AuthFailedError):
error = 'block_global_ip_login' error = 'block_global_ip_login'
def __init__(self, username, ip, **kwargs): def __init__(self, username, ip, **kwargs):
self.msg = _("IP is not allowed") self.msg = block_ip_login_msg.format(settings.SECURITY_LOGIN_IP_LIMIT_TIME)
LoginIpBlockUtil(ip).set_block_if_need() LoginIpBlockUtil(ip).set_block_if_need()
super().__init__(username=username, ip=ip, **kwargs) super().__init__(username=username, ip=ip, **kwargs)
@ -133,7 +137,7 @@ class CredentialError(
block_time = settings.SECURITY_LOGIN_LIMIT_TIME block_time = settings.SECURITY_LOGIN_LIMIT_TIME
if times_remainder < 1: if times_remainder < 1:
self.msg = block_login_msg.format(settings.SECURITY_LOGIN_LIMIT_TIME) self.msg = block_user_login_msg.format(settings.SECURITY_LOGIN_LIMIT_TIME)
return return
default_msg = invalid_login_msg.format( default_msg = invalid_login_msg.format(
@ -184,7 +188,7 @@ class BlockLoginError(AuthFailedNeedBlockMixin, AuthFailedError):
error = 'block_login' error = 'block_login'
def __init__(self, username, ip): def __init__(self, username, ip):
self.msg = block_login_msg.format(settings.SECURITY_LOGIN_LIMIT_TIME) self.msg = block_user_login_msg.format(settings.SECURITY_LOGIN_LIMIT_TIME)
super().__init__(username=username, ip=ip) super().__init__(username=username, ip=ip)

View File

@ -291,8 +291,11 @@ class Config(dict):
'SECURITY_COMMAND_EXECUTION': True, 'SECURITY_COMMAND_EXECUTION': True,
'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True, 'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True,
'SECURITY_VIEW_AUTH_NEED_MFA': True, 'SECURITY_VIEW_AUTH_NEED_MFA': True,
'SECURITY_LOGIN_LIMIT_COUNT': 7,
'SECURITY_LOGIN_IP_BLACK_LIST': [], 'SECURITY_LOGIN_IP_BLACK_LIST': [],
'SECURITY_LOGIN_IP_WHITE_LIST': [],
'SECURITY_LOGIN_LIMIT_COUNT': 7,
'SECURITY_LOGIN_IP_LIMIT_COUNT': 99999,
'SECURITY_LOGIN_IP_LIMIT_TIME': 30,
'SECURITY_LOGIN_LIMIT_TIME': 30, 'SECURITY_LOGIN_LIMIT_TIME': 30,
'SECURITY_MAX_IDLE_TIME': 30, 'SECURITY_MAX_IDLE_TIME': 30,
'SECURITY_PASSWORD_EXPIRATION_TIME': 9999, 'SECURITY_PASSWORD_EXPIRATION_TIME': 9999,

View File

@ -35,6 +35,9 @@ SECURITY_MFA_AUTH = CONFIG.SECURITY_MFA_AUTH
SECURITY_COMMAND_EXECUTION = CONFIG.SECURITY_COMMAND_EXECUTION SECURITY_COMMAND_EXECUTION = CONFIG.SECURITY_COMMAND_EXECUTION
SECURITY_LOGIN_LIMIT_COUNT = CONFIG.SECURITY_LOGIN_LIMIT_COUNT SECURITY_LOGIN_LIMIT_COUNT = CONFIG.SECURITY_LOGIN_LIMIT_COUNT
SECURITY_LOGIN_IP_BLACK_LIST = CONFIG.SECURITY_LOGIN_IP_BLACK_LIST SECURITY_LOGIN_IP_BLACK_LIST = CONFIG.SECURITY_LOGIN_IP_BLACK_LIST
SECURITY_LOGIN_IP_WHITE_LIST = CONFIG.SECURITY_LOGIN_IP_WHITE_LIST
SECURITY_LOGIN_IP_LIMIT_COUNT = CONFIG.SECURITY_LOGIN_IP_LIMIT_COUNT
SECURITY_LOGIN_IP_LIMIT_TIME = CONFIG.SECURITY_LOGIN_IP_LIMIT_TIME
SECURITY_LOGIN_LIMIT_TIME = CONFIG.SECURITY_LOGIN_LIMIT_TIME # Unit: minute SECURITY_LOGIN_LIMIT_TIME = CONFIG.SECURITY_LOGIN_LIMIT_TIME # Unit: minute
SECURITY_MAX_IDLE_TIME = CONFIG.SECURITY_MAX_IDLE_TIME # Unit: minute SECURITY_MAX_IDLE_TIME = CONFIG.SECURITY_MAX_IDLE_TIME # Unit: minute
SECURITY_PASSWORD_EXPIRATION_TIME = CONFIG.SECURITY_PASSWORD_EXPIRATION_TIME # Unit: day SECURITY_PASSWORD_EXPIRATION_TIME = CONFIG.SECURITY_PASSWORD_EXPIRATION_TIME # Unit: day

View File

@ -7,7 +7,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: 2021-11-18 19:00+0800\n" "POT-Creation-Date: 2021-11-19 10:40+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\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"
@ -1619,13 +1619,19 @@ msgstr ""
"您输入的用户名或密码不正确,请重新输入。 您还可以尝试 {times_try} 次(账号将" "您输入的用户名或密码不正确,请重新输入。 您还可以尝试 {times_try} 次(账号将"
"被临时 锁定 {block_time} 分钟)" "被临时 锁定 {block_time} 分钟)"
#: authentication/errors.py:55 authentication/errors.py:59 #: authentication/errors.py:55 authentication/errors.py:63
msgid "" msgid ""
"The account has been locked (please contact admin to unlock it or try again " "The account has been locked (please contact admin to unlock it or try again "
"after {} minutes)" "after {} minutes)"
msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)" msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)"
#: authentication/errors.py:63 #: authentication/errors.py:59
msgid ""
"The ip has been locked (please contact admin to unlock it or try again after "
"{} minutes)"
msgstr "IP已被锁定请联系管理员解锁 或 {}分钟后重试)"
#: authentication/errors.py:67
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"{error}, You can also try {times_try} times (The account will be temporarily " "{error}, You can also try {times_try} times (The account will be temporarily "
@ -1633,63 +1639,63 @@ msgid ""
msgstr "" msgstr ""
"{error},您还可以尝试 {times_try} 次(账号将被临时锁定 {block_time} 分钟)" "{error},您还可以尝试 {times_try} 次(账号将被临时锁定 {block_time} 分钟)"
#: authentication/errors.py:67 #: authentication/errors.py:71
msgid "MFA required" msgid "MFA required"
msgstr "需要 MFA 认证" msgstr "需要 MFA 认证"
#: authentication/errors.py:68 #: authentication/errors.py:72
msgid "MFA not set, please set it first" msgid "MFA not set, please set it first"
msgstr "MFA 没有设置,请先完成设置" msgstr "MFA 没有设置,请先完成设置"
#: authentication/errors.py:69 #: authentication/errors.py:73
msgid "Login confirm required" msgid "Login confirm required"
msgstr "需要登录复核" msgstr "需要登录复核"
#: authentication/errors.py:70 #: authentication/errors.py:74
msgid "Wait login confirm ticket for accept" msgid "Wait login confirm ticket for accept"
msgstr "等待登录复核处理" msgstr "等待登录复核处理"
#: authentication/errors.py:71 #: authentication/errors.py:75
msgid "Login confirm ticket was {}" msgid "Login confirm ticket was {}"
msgstr "登录复核 {}" msgstr "登录复核 {}"
#: authentication/errors.py:121 authentication/errors.py:251 #: authentication/errors.py:255
msgid "IP is not allowed" msgid "IP is not allowed"
msgstr "来源 IP 不被允许登录" msgstr "来源 IP 不被允许登录"
#: authentication/errors.py:258 #: authentication/errors.py:262
msgid "Time Period is not allowed" msgid "Time Period is not allowed"
msgstr "该 时间段 不被允许登录" msgstr "该 时间段 不被允许登录"
#: authentication/errors.py:291 #: authentication/errors.py:295
msgid "SSO auth closed" msgid "SSO auth closed"
msgstr "SSO 认证关闭了" msgstr "SSO 认证关闭了"
#: authentication/errors.py:296 authentication/mixins.py:360 #: authentication/errors.py:300 authentication/mixins.py:360
msgid "Your password is too simple, please change it for security" msgid "Your password is too simple, please change it for security"
msgstr "你的密码过于简单,为了安全,请修改" msgstr "你的密码过于简单,为了安全,请修改"
#: authentication/errors.py:305 authentication/mixins.py:367 #: authentication/errors.py:309 authentication/mixins.py:367
msgid "You should to change your password before login" msgid "You should to change your password before login"
msgstr "登录完成前,请先修改密码" msgstr "登录完成前,请先修改密码"
#: authentication/errors.py:314 authentication/mixins.py:374 #: authentication/errors.py:318 authentication/mixins.py:374
msgid "Your password has expired, please reset before logging in" msgid "Your password has expired, please reset before logging in"
msgstr "您的密码已过期,先修改再登录" msgstr "您的密码已过期,先修改再登录"
#: authentication/errors.py:348 #: authentication/errors.py:352
msgid "Your password is invalid" msgid "Your password is invalid"
msgstr "您的密码无效" msgstr "您的密码无效"
#: authentication/errors.py:353 #: authentication/errors.py:357
msgid "Please enter MFA code" msgid "Please enter MFA code"
msgstr "请输入 MFA 验证码" msgstr "请输入 MFA 验证码"
#: authentication/errors.py:358 #: authentication/errors.py:362
msgid "Please enter SMS code" msgid "Please enter SMS code"
msgstr "请输入短信验证码" msgstr "请输入短信验证码"
#: authentication/errors.py:363 users/exceptions.py:15 #: authentication/errors.py:367 users/exceptions.py:15
msgid "Phone not set" msgid "Phone not set"
msgstr "手机号没有设置" msgstr "手机号没有设置"
@ -3339,12 +3345,12 @@ msgid "Global MFA auth"
msgstr "全局启用 MFA 认证" msgstr "全局启用 MFA 认证"
#: settings/serializers/security.py:50 #: settings/serializers/security.py:50
msgid "Limit the number of login failures" msgid "Limit the number of user login failures"
msgstr "限制登录失败次数" msgstr "限制用户登录失败次数"
#: settings/serializers/security.py:54 #: settings/serializers/security.py:54
msgid "Block logon interval" msgid "Block user login interval"
msgstr "禁止登录时间间隔" msgstr "禁止用户登录时间间隔"
#: settings/serializers/security.py:56 #: settings/serializers/security.py:56
msgid "" msgid ""
@ -3352,11 +3358,25 @@ msgid ""
"times, no login is allowed during this time interval." "times, no login is allowed during this time interval."
msgstr "单位:分, 当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录" msgstr "单位:分, 当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录"
#: settings/serializers/security.py:61 #: settings/serializers/security.py:62
msgid "Login IP Black List" msgid "Limit the number of IP login failures"
msgstr "登录 IP 黑名单" msgstr "限制IP登录失败次数"
#: settings/serializers/security.py:64 #: settings/serializers/security.py:66
msgid "Block IP login interval"
msgstr "禁止IP登录时间间隔"
#: settings/serializers/security.py:68
msgid ""
"Unit: minute, If the IP has failed to log in for a limited number of times, "
"no login is allowed during this time interval."
msgstr "单位:分, 当IP登录失败次数达到限制后那么在此时间间隔内禁止登录"
#: settings/serializers/security.py:73
msgid "Login IP White List"
msgstr "IP登录白名单"
#: settings/serializers/security.py:76 settings/serializers/security.py:84
msgid "" msgid ""
"Format for comma-delimited string. Such as: 192.168.10.1, 192.168.1.0/24, " "Format for comma-delimited string. Such as: 192.168.10.1, 192.168.1.0/24, "
"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64" "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64"
@ -3364,11 +3384,15 @@ msgstr ""
"格式为逗号分隔的字符串。例如: 192.168.10.1, 192.168.1.0/24, " "格式为逗号分隔的字符串。例如: 192.168.10.1, 192.168.1.0/24, "
"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (支持网域)" "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (支持网域)"
#: settings/serializers/security.py:70 #: settings/serializers/security.py:81
msgid "Login IP Black List"
msgstr "IP登录黑名单"
#: settings/serializers/security.py:90
msgid "User password expiration" msgid "User password expiration"
msgstr "用户密码过期时间" msgstr "用户密码过期时间"
#: settings/serializers/security.py:72 #: settings/serializers/security.py:92
msgid "" msgid ""
"Unit: day, If the user does not update the password during the time, the " "Unit: day, If the user does not update the password during the time, the "
"user password will expire failure;The password expiration reminder mail will " "user password will expire failure;The password expiration reminder mail will "
@ -3378,55 +3402,55 @@ msgstr ""
"单位:天, 如果用户在此期间没有更新密码,用户密码将过期失效; 密码过期提醒邮件" "单位:天, 如果用户在此期间没有更新密码,用户密码将过期失效; 密码过期提醒邮件"
"将在密码过期前5天内由系统每天自动发送给用户" "将在密码过期前5天内由系统每天自动发送给用户"
#: settings/serializers/security.py:79 #: settings/serializers/security.py:99
msgid "Number of repeated historical passwords" msgid "Number of repeated historical passwords"
msgstr "不能设置近几次密码" msgstr "不能设置近几次密码"
#: settings/serializers/security.py:81 #: settings/serializers/security.py:101
msgid "" msgid ""
"Tip: When the user resets the password, it cannot be the previous n " "Tip: When the user resets the password, it cannot be the previous n "
"historical passwords of the user" "historical passwords of the user"
msgstr "提示:用户重置密码时,不能为该用户前几次使用过的密码" msgstr "提示:用户重置密码时,不能为该用户前几次使用过的密码"
#: settings/serializers/security.py:86 #: settings/serializers/security.py:106
msgid "Only single device login" msgid "Only single device login"
msgstr "仅一台设备登录" msgstr "仅一台设备登录"
#: settings/serializers/security.py:87 #: settings/serializers/security.py:107
msgid "Next device login, pre login will be logout" msgid "Next device login, pre login will be logout"
msgstr "下个设备登录,上次登录会被顶掉" msgstr "下个设备登录,上次登录会被顶掉"
#: settings/serializers/security.py:90 #: settings/serializers/security.py:110
msgid "Only exist user login" msgid "Only exist user login"
msgstr "仅已存在用户登录" msgstr "仅已存在用户登录"
#: settings/serializers/security.py:91 #: settings/serializers/security.py:111
msgid "If enable, CAS、OIDC auth will be failed, if user not exist yet" msgid "If enable, CAS、OIDC auth will be failed, if user not exist yet"
msgstr "开启后如果系统中不存在该用户CAS、OIDC 登录将会失败" msgstr "开启后如果系统中不存在该用户CAS、OIDC 登录将会失败"
#: settings/serializers/security.py:94 #: settings/serializers/security.py:114
msgid "Only from source login" msgid "Only from source login"
msgstr "仅从用户来源登录" msgstr "仅从用户来源登录"
#: settings/serializers/security.py:95 #: settings/serializers/security.py:115
msgid "Only log in from the user source property" msgid "Only log in from the user source property"
msgstr "开启后如果用户来源为本地CAS、OIDC 登录将会失败" msgstr "开启后如果用户来源为本地CAS、OIDC 登录将会失败"
#: settings/serializers/security.py:99 #: settings/serializers/security.py:119
msgid "MFA verify TTL" msgid "MFA verify TTL"
msgstr "MFA 校验有效期" msgstr "MFA 校验有效期"
#: settings/serializers/security.py:101 #: settings/serializers/security.py:121
msgid "" msgid ""
"Unit: second, The verification MFA takes effect only when you view the " "Unit: second, The verification MFA takes effect only when you view the "
"account password" "account password"
msgstr "单位: 秒, 目前仅在查看账号密码校验 MFA 时生效" msgstr "单位: 秒, 目前仅在查看账号密码校验 MFA 时生效"
#: settings/serializers/security.py:106 #: settings/serializers/security.py:126
msgid "Enable Login dynamic code" msgid "Enable Login dynamic code"
msgstr "启用登录附加码" msgstr "启用登录附加码"
#: settings/serializers/security.py:107 #: settings/serializers/security.py:127
msgid "" msgid ""
"The password and additional code are sent to a third party authentication " "The password and additional code are sent to a third party authentication "
"system for verification" "system for verification"
@ -3434,89 +3458,89 @@ msgstr ""
"密码和附加码一并发送给第三方认证系统进行校验, 如:有的第三方认证系统,需要 密" "密码和附加码一并发送给第三方认证系统进行校验, 如:有的第三方认证系统,需要 密"
"码+6位数字 完成认证" "码+6位数字 完成认证"
#: settings/serializers/security.py:112 #: settings/serializers/security.py:132
msgid "MFA in login page" msgid "MFA in login page"
msgstr "MFA 在登录页面输入" msgstr "MFA 在登录页面输入"
#: settings/serializers/security.py:113 #: settings/serializers/security.py:133
msgid "Eu security regulations(GDPR) require MFA to be on the login page" msgid "Eu security regulations(GDPR) require MFA to be on the login page"
msgstr "欧盟数据安全法规(GDPR) 要求 MFA 在登录页面,来确保系统登录安全" msgstr "欧盟数据安全法规(GDPR) 要求 MFA 在登录页面,来确保系统登录安全"
#: settings/serializers/security.py:116 #: settings/serializers/security.py:136
msgid "Enable Login captcha" msgid "Enable Login captcha"
msgstr "启用登录验证码" msgstr "启用登录验证码"
#: settings/serializers/security.py:117 #: settings/serializers/security.py:137
msgid "Enable captcha to prevent robot authentication" msgid "Enable captcha to prevent robot authentication"
msgstr "开启验证码,防止机器人登录" msgstr "开启验证码,防止机器人登录"
#: settings/serializers/security.py:137 #: settings/serializers/security.py:157
msgid "Enable terminal register" msgid "Enable terminal register"
msgstr "终端注册" msgstr "终端注册"
#: settings/serializers/security.py:139 #: settings/serializers/security.py:159
msgid "" msgid ""
"Allow terminal register, after all terminal setup, you should disable this " "Allow terminal register, after all terminal setup, you should disable this "
"for security" "for security"
msgstr "是否允许终端注册,当所有终端启动后,为了安全应该关闭" msgstr "是否允许终端注册,当所有终端启动后,为了安全应该关闭"
#: settings/serializers/security.py:143 #: settings/serializers/security.py:163
msgid "Enable watermark" msgid "Enable watermark"
msgstr "开启水印" msgstr "开启水印"
#: settings/serializers/security.py:144 #: settings/serializers/security.py:164
msgid "Enabled, the web session and replay contains watermark information" msgid "Enabled, the web session and replay contains watermark information"
msgstr "启用后Web 会话和录像将包含水印信息" msgstr "启用后Web 会话和录像将包含水印信息"
#: settings/serializers/security.py:148 #: settings/serializers/security.py:168
msgid "Connection max idle time" msgid "Connection max idle time"
msgstr "连接最大空闲时间" msgstr "连接最大空闲时间"
#: settings/serializers/security.py:149 #: settings/serializers/security.py:169
msgid "If idle time more than it, disconnect connection Unit: minute" msgid "If idle time more than it, disconnect connection Unit: minute"
msgstr "提示:如果超过该配置没有操作,连接会被断开 (单位:分)" msgstr "提示:如果超过该配置没有操作,连接会被断开 (单位:分)"
#: settings/serializers/security.py:152 #: settings/serializers/security.py:172
msgid "Remember manual auth" msgid "Remember manual auth"
msgstr "保存手动输入密码" msgstr "保存手动输入密码"
#: settings/serializers/security.py:155 #: settings/serializers/security.py:175
msgid "Enable change auth secure mode" msgid "Enable change auth secure mode"
msgstr "启用改密安全模式" msgstr "启用改密安全模式"
#: settings/serializers/security.py:158 #: settings/serializers/security.py:178
msgid "Insecure command alert" msgid "Insecure command alert"
msgstr "危险命令告警" msgstr "危险命令告警"
#: settings/serializers/security.py:161 #: settings/serializers/security.py:181
msgid "Email recipient" msgid "Email recipient"
msgstr "邮件收件人" msgstr "邮件收件人"
#: settings/serializers/security.py:162 #: settings/serializers/security.py:182
msgid "Multiple user using , split" msgid "Multiple user using , split"
msgstr "多个用户,使用 , 分割" msgstr "多个用户,使用 , 分割"
#: settings/serializers/security.py:165 #: settings/serializers/security.py:185
msgid "Batch command execution" msgid "Batch command execution"
msgstr "批量命令执行" msgstr "批量命令执行"
#: settings/serializers/security.py:166 #: settings/serializers/security.py:186
msgid "Allow user run batch command or not using ansible" msgid "Allow user run batch command or not using ansible"
msgstr "是否允许用户使用 ansible 执行批量命令" msgstr "是否允许用户使用 ansible 执行批量命令"
#: settings/serializers/security.py:169 #: settings/serializers/security.py:189
msgid "Session share" msgid "Session share"
msgstr "会话分享" msgstr "会话分享"
#: settings/serializers/security.py:170 #: settings/serializers/security.py:190
msgid "Enabled, Allows user active session to be shared with other users" msgid "Enabled, Allows user active session to be shared with other users"
msgstr "开启后允许用户分享已连接的资产会话给它人,协同工作" msgstr "开启后允许用户分享已连接的资产会话给它人,协同工作"
#: settings/serializers/security.py:173 #: settings/serializers/security.py:193
msgid "Remote Login Protection" msgid "Remote Login Protection"
msgstr "异地登录保护" msgstr "异地登录保护"
#: settings/serializers/security.py:175 #: settings/serializers/security.py:195
msgid "" msgid ""
"The system determines whether the login IP address belongs to a common login " "The system determines whether the login IP address belongs to a common login "
"city. If the account is logged in from a common login city, the system sends " "city. If the account is logged in from a common login city, the system sends "

View File

@ -47,16 +47,36 @@ class SecurityAuthSerializer(serializers.Serializer):
) )
SECURITY_LOGIN_LIMIT_COUNT = serializers.IntegerField( SECURITY_LOGIN_LIMIT_COUNT = serializers.IntegerField(
min_value=3, max_value=99999, min_value=3, max_value=99999,
label=_('Limit the number of login failures') label=_('Limit the number of user login failures')
) )
SECURITY_LOGIN_LIMIT_TIME = serializers.IntegerField( SECURITY_LOGIN_LIMIT_TIME = serializers.IntegerField(
min_value=5, max_value=99999, required=True, min_value=5, max_value=99999, required=True,
label=_('Block logon interval'), label=_('Block user login interval'),
help_text=_( help_text=_(
'Unit: minute, If the user has failed to log in for a limited number of times, ' 'Unit: minute, If the user has failed to log in for a limited number of times, '
'no login is allowed during this time interval.' 'no login is allowed during this time interval.'
) )
) )
SECURITY_LOGIN_IP_LIMIT_COUNT = serializers.IntegerField(
min_value=3, max_value=99999,
label=_('Limit the number of IP login failures')
)
SECURITY_LOGIN_IP_LIMIT_TIME = serializers.IntegerField(
min_value=5, max_value=99999, required=True,
label=_('Block IP login interval'),
help_text=_(
'Unit: minute, If the IP has failed to log in for a limited number of times, '
'no login is allowed during this time interval.'
)
)
SECURITY_LOGIN_IP_WHITE_LIST = serializers.ListField(
default=[], label=_('Login IP White List'), allow_empty=True,
child=serializers.CharField(max_length=1024, validators=[ip_child_validator]),
help_text=_(
'Format for comma-delimited string. Such as: '
'192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64'
)
)
SECURITY_LOGIN_IP_BLACK_LIST = serializers.ListField( SECURITY_LOGIN_IP_BLACK_LIST = serializers.ListField(
default=[], label=_('Login 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]), child=serializers.CharField(max_length=1024, validators=[ip_child_validator]),

View File

@ -180,34 +180,38 @@ class BlockGlobalIpUtilBase:
self.ip = ip self.ip = ip
self.limit_key = self.LIMIT_KEY_TMPL.format(ip) self.limit_key = self.LIMIT_KEY_TMPL.format(ip)
self.block_key = self.BLOCK_KEY_TMPL.format(ip) self.block_key = self.BLOCK_KEY_TMPL.format(ip)
self.key_ttl = int(settings.SECURITY_LOGIN_LIMIT_TIME) * 60 self.key_ttl = int(settings.SECURITY_LOGIN_IP_LIMIT_TIME) * 60
@property @property
def ip_in_black_list(self): def ip_in_black_list(self):
return self.ip in settings.SECURITY_LOGIN_IP_BLACK_LIST return self.ip in settings.SECURITY_LOGIN_IP_BLACK_LIST
def set_block_if_need(self): @property
if not self.ip_in_black_list: def ip_in_white_list(self):
return return self.ip in settings.SECURITY_LOGIN_IP_WHITE_LIST
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 def set_block_if_need(self):
if count < limit_count: if not self.ip_in_white_list and not self.ip_in_black_list:
return count = cache.get(self.limit_key, 0)
cache.set(self.block_key, True, self.key_ttl) count += 1
cache.set(self.limit_key, count, self.key_ttl)
limit_count = settings.SECURITY_LOGIN_IP_LIMIT_COUNT
if count < limit_count:
return
cache.set(self.block_key, True, self.key_ttl)
def clean_block_if_need(self): def clean_block_if_need(self):
if not self.ip_in_black_list:
return
cache.delete(self.limit_key) cache.delete(self.limit_key)
cache.delete(self.block_key) cache.delete(self.block_key)
def is_block(self): def is_block(self):
if not self.ip_in_black_list: if self.ip_in_white_list:
return False return False
return bool(cache.get(self.block_key)) if self.ip_in_black_list:
return True
if not self.ip_in_white_list and not self.ip_in_black_list:
return bool(cache.get(self.block_key))
class LoginBlockUtil(BlockUtilBase): class LoginBlockUtil(BlockUtilBase):