mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-20 02:48:51 +00:00
Add option to freeze user account when failed login attemts exceed limit
This commit is contained in:
@@ -24,6 +24,7 @@ from seahub.auth.forms import PasswordResetForm, SetPasswordForm, PasswordChange
|
||||
from seahub.auth.tokens import default_token_generator
|
||||
from seahub.base.accounts import User
|
||||
from seahub.options.models import UserOptions
|
||||
from seahub.profile.models import Profile
|
||||
from seahub.utils import is_ldap_user
|
||||
from seahub.utils.http import is_safe_url
|
||||
from seahub.utils.ip import get_remote_ip
|
||||
@@ -111,6 +112,16 @@ def _clear_login_failed_attempts(request):
|
||||
cache.delete(LOGIN_ATTEMPT_PREFIX + username)
|
||||
cache.delete(LOGIN_ATTEMPT_PREFIX + ip)
|
||||
|
||||
def _handle_login_form_valid(request, user, redirect_to, remember_me):
|
||||
if UserOptions.objects.passwd_change_required(
|
||||
user.username):
|
||||
redirect_to = reverse('auth_password_change')
|
||||
request.session['force_passwd_change'] = True
|
||||
|
||||
# password is valid, log user in
|
||||
request.session['remember_me'] = remember_me
|
||||
return log_user_in(request, user, redirect_to)
|
||||
|
||||
@csrf_protect
|
||||
@never_cache
|
||||
def login(request, template_name='registration/login.html',
|
||||
@@ -131,49 +142,66 @@ def login(request, template_name='registration/login.html',
|
||||
remember_me = True if request.REQUEST.get('remember_me',
|
||||
'') == 'on' else False
|
||||
|
||||
if failed_attempt >= settings.LOGIN_ATTEMPT_LIMIT:
|
||||
# have captcha
|
||||
form = CaptchaAuthenticationForm(data=request.POST)
|
||||
if form.is_valid():
|
||||
if UserOptions.objects.passwd_change_required(
|
||||
form.get_user().username):
|
||||
redirect_to = reverse('auth_password_change')
|
||||
request.session['force_passwd_change'] = True
|
||||
if failed_attempt >= config.LOGIN_ATTEMPT_LIMIT:
|
||||
if bool(config.FREEZE_USER_ON_LOGIN_FAILED) is True:
|
||||
# log user in if password is valid otherwise freeze account
|
||||
form = authentication_form(data=request.POST)
|
||||
if form.is_valid():
|
||||
return _handle_login_form_valid(request, form.get_user(),
|
||||
redirect_to, remember_me)
|
||||
else:
|
||||
# freeze user account anyway
|
||||
login = request.REQUEST.get('login', '')
|
||||
email = Profile.objects.get_username_by_login_id(login)
|
||||
if email is None:
|
||||
email = login
|
||||
|
||||
# captcha & passwod is valid, log user in
|
||||
request.session['remember_me'] = remember_me
|
||||
return log_user_in(request, form.get_user(), redirect_to)
|
||||
try:
|
||||
user = User.objects.get(email)
|
||||
user.is_active = False
|
||||
user.save()
|
||||
except User.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
# show page with captcha and increase failed login attempts
|
||||
_incr_login_faied_attempts(username=username, ip=ip)
|
||||
# log user in if password is valid otherwise show captcha
|
||||
form = CaptchaAuthenticationForm(data=request.POST)
|
||||
if form.is_valid():
|
||||
return _handle_login_form_valid(request, form.get_user(),
|
||||
redirect_to, remember_me)
|
||||
else:
|
||||
# show page with captcha and increase failed login attempts
|
||||
_incr_login_faied_attempts(username=username, ip=ip)
|
||||
else:
|
||||
# login failed attempts < limit
|
||||
form = authentication_form(data=request.POST)
|
||||
if form.is_valid():
|
||||
if UserOptions.objects.passwd_change_required(
|
||||
form.get_user().username):
|
||||
redirect_to = reverse('auth_password_change')
|
||||
request.session['force_passwd_change'] = True
|
||||
|
||||
# password is valid, log user in
|
||||
request.session['remember_me'] = remember_me
|
||||
return log_user_in(request, form.get_user(), redirect_to)
|
||||
return _handle_login_form_valid(request, form.get_user(),
|
||||
redirect_to, remember_me)
|
||||
else:
|
||||
# increase failed attempts
|
||||
login = urlquote(request.REQUEST.get('login', '').strip())
|
||||
failed_attempt = _incr_login_faied_attempts(username=login,
|
||||
ip=ip)
|
||||
|
||||
if failed_attempt >= settings.LOGIN_ATTEMPT_LIMIT:
|
||||
if failed_attempt >= config.LOGIN_ATTEMPT_LIMIT:
|
||||
logger.warn('Login attempt limit reached, email/username: %s, ip: %s, attemps: %d' %
|
||||
(login, ip, failed_attempt))
|
||||
form = CaptchaAuthenticationForm()
|
||||
|
||||
if bool(config.FREEZE_USER_ON_LOGIN_FAILED) is True:
|
||||
form = authentication_form(data=request.POST)
|
||||
else:
|
||||
form = CaptchaAuthenticationForm()
|
||||
else:
|
||||
form = authentication_form(data=request.POST)
|
||||
else:
|
||||
### GET
|
||||
if failed_attempt >= settings.LOGIN_ATTEMPT_LIMIT:
|
||||
if failed_attempt >= config.LOGIN_ATTEMPT_LIMIT:
|
||||
logger.warn('Login attempt limit reached, ip: %s, attempts: %d' %
|
||||
(ip, failed_attempt))
|
||||
form = CaptchaAuthenticationForm(request)
|
||||
if bool(config.FREEZE_USER_ON_LOGIN_FAILED) is True:
|
||||
form = authentication_form(data=request.POST)
|
||||
else:
|
||||
form = CaptchaAuthenticationForm()
|
||||
else:
|
||||
form = authentication_form(request)
|
||||
|
||||
|
@@ -442,6 +442,7 @@ LOGGING = {
|
||||
#Login Attempt
|
||||
LOGIN_ATTEMPT_LIMIT = 3
|
||||
LOGIN_ATTEMPT_TIMEOUT = 15 * 60 # in seconds (default: 15 minutes)
|
||||
FREEZE_USER_ON_LOGIN_FAILED = False # deactivate user account when login attempts exceed limit
|
||||
|
||||
# Age of cookie, in seconds (default: 1 day).
|
||||
SESSION_COOKIE_AGE = 24 * 60 * 60
|
||||
@@ -629,6 +630,9 @@ CONSTANCE_CONFIG = {
|
||||
'ACTIVATE_AFTER_REGISTRATION': (ACTIVATE_AFTER_REGISTRATION,''),
|
||||
'REGISTRATION_SEND_MAIL': (REGISTRATION_SEND_MAIL ,''),
|
||||
'LOGIN_REMEMBER_DAYS': (LOGIN_REMEMBER_DAYS,''),
|
||||
'LOGIN_ATTEMPT_LIMIT': (LOGIN_ATTEMPT_LIMIT, ''),
|
||||
'FREEZE_USER_ON_LOGIN_FAILED': (FREEZE_USER_ON_LOGIN_FAILED, ''),
|
||||
|
||||
'ENABLE_USER_CREATE_ORG_REPO': (ENABLE_USER_CREATE_ORG_REPO, ''),
|
||||
|
||||
'ENABLE_ENCRYPTED_LIBRARY': (ENABLE_ENCRYPTED_LIBRARY,''),
|
||||
|
@@ -40,6 +40,15 @@
|
||||
{% with type="input" setting_display_name="keep sign in" help_tip="Number of days that keep user sign in." setting_name="LOGIN_REMEMBER_DAYS" setting_val=config_dict.LOGIN_REMEMBER_DAYS %}
|
||||
{% include "snippets/web_settings_form.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% with type="input" setting_display_name="LOGIN_ATTEMPT_LIMIT" help_tip="The maximum number of failed login attempts before showing CAPTCHA." setting_name="LOGIN_ATTEMPT_LIMIT" setting_val=config_dict.LOGIN_ATTEMPT_LIMIT %}
|
||||
{% include "snippets/web_settings_form.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% with type="checkbox" setting_display_name="FREEZE_USER_ON_LOGIN_FAILED" help_tip="Freeze user account when failed login attempts exceed limit." setting_name="FREEZE_USER_ON_LOGIN_FAILED" setting_val=config_dict.FREEZE_USER_ON_LOGIN_FAILED %}
|
||||
{% include "snippets/web_settings_form.html" %}
|
||||
{% endwith %}
|
||||
|
||||
</div>
|
||||
|
||||
<h4>Password</h4>
|
||||
|
@@ -2162,7 +2162,8 @@ def sys_settings(request):
|
||||
'ENABLE_REPO_HISTORY_SETTING', 'USER_STRONG_PASSWORD_REQUIRED',
|
||||
'ENABLE_ENCRYPTED_LIBRARY', 'USER_PASSWORD_MIN_LENGTH',
|
||||
'USER_PASSWORD_STRENGTH_LEVEL', 'SHARE_LINK_PASSWORD_MIN_LENGTH',
|
||||
'ENABLE_USER_CREATE_ORG_REPO', 'FORCE_PASSWORD_CHANGE'
|
||||
'ENABLE_USER_CREATE_ORG_REPO', 'FORCE_PASSWORD_CHANGE',
|
||||
'LOGIN_ATTEMPT_LIMIT', 'FREEZE_USER_ON_LOGIN_FAILED',
|
||||
)
|
||||
|
||||
STRING_WEB_SETTINGS = ('SERVICE_URL', 'FILE_SERVER_ROOT',)
|
||||
|
Reference in New Issue
Block a user