mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-20 02:48:51 +00:00
[passwd strength] add STRONG password check(default not enabled) when user sign-up or change-password
This commit is contained in:
@@ -7,10 +7,13 @@ from seahub.base.accounts import User
|
|||||||
from seahub.auth import authenticate
|
from seahub.auth import authenticate
|
||||||
from seahub.auth.tokens import default_token_generator
|
from seahub.auth.tokens import default_token_generator
|
||||||
from seahub.utils import IS_EMAIL_CONFIGURED, send_html_email, \
|
from seahub.utils import IS_EMAIL_CONFIGURED, send_html_email, \
|
||||||
is_valid_username, is_ldap_user
|
is_valid_username, is_ldap_user, is_user_password_strong
|
||||||
|
|
||||||
from captcha.fields import CaptchaField
|
from captcha.fields import CaptchaField
|
||||||
|
|
||||||
|
from seahub.settings import USER_STRONG_PASSWORD_REQUIRED, \
|
||||||
|
USER_PASSWORD_STRENGTH_LEVEL, USER_PASSWORD_MIN_LENGTH
|
||||||
|
|
||||||
class AuthenticationForm(forms.Form):
|
class AuthenticationForm(forms.Form):
|
||||||
"""
|
"""
|
||||||
Base class for authenticating users. Extend this to get a form that accepts
|
Base class for authenticating users. Extend this to get a form that accepts
|
||||||
@@ -124,6 +127,18 @@ class SetPasswordForm(forms.Form):
|
|||||||
|
|
||||||
super(SetPasswordForm, self).__init__(*args, **kwargs)
|
super(SetPasswordForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def clean_new_password1(self):
|
||||||
|
if 'new_password1' in self.cleaned_data:
|
||||||
|
pwd = self.cleaned_data['new_password1']
|
||||||
|
|
||||||
|
if USER_STRONG_PASSWORD_REQUIRED is True:
|
||||||
|
if is_user_password_strong(pwd) is True:
|
||||||
|
return pwd
|
||||||
|
else:
|
||||||
|
raise forms.ValidationError(_("%s characters or more, include %s types or more of these: letters(case sensitive), numbers, and symbols") % (USER_PASSWORD_MIN_LENGTH, USER_PASSWORD_STRENGTH_LEVEL))
|
||||||
|
else:
|
||||||
|
return pwd
|
||||||
|
|
||||||
def clean_new_password2(self):
|
def clean_new_password2(self):
|
||||||
password1 = self.cleaned_data.get('new_password1')
|
password1 = self.cleaned_data.get('new_password1')
|
||||||
password2 = self.cleaned_data.get('new_password2')
|
password2 = self.cleaned_data.get('new_password2')
|
||||||
|
@@ -25,6 +25,8 @@ from seahub.auth.tokens import default_token_generator
|
|||||||
from seahub.base.accounts import User
|
from seahub.base.accounts import User
|
||||||
from seahub.utils import is_ldap_user
|
from seahub.utils import is_ldap_user
|
||||||
from seahub.utils.ip import get_remote_ip
|
from seahub.utils.ip import get_remote_ip
|
||||||
|
from seahub.settings import USER_PASSWORD_MIN_LENGTH, \
|
||||||
|
USER_STRONG_PASSWORD_REQUIRED, USER_PASSWORD_STRENGTH_LEVEL
|
||||||
|
|
||||||
# Get an instance of a logger
|
# Get an instance of a logger
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -352,8 +354,12 @@ def password_change(request, template_name='registration/password_change_form.ht
|
|||||||
return HttpResponseRedirect(post_change_redirect)
|
return HttpResponseRedirect(post_change_redirect)
|
||||||
else:
|
else:
|
||||||
form = password_change_form(user=request.user)
|
form = password_change_form(user=request.user)
|
||||||
|
|
||||||
return render_to_response(template_name, {
|
return render_to_response(template_name, {
|
||||||
'form': form,
|
'form': form,
|
||||||
|
'min_len': USER_PASSWORD_MIN_LENGTH,
|
||||||
|
'strong_pwd_required': USER_STRONG_PASSWORD_REQUIRED,
|
||||||
|
'level': USER_PASSWORD_STRENGTH_LEVEL,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
def password_change_done(request, template_name='registration/password_change_done.html'):
|
def password_change_done(request, template_name='registration/password_change_done.html'):
|
||||||
|
@@ -13,12 +13,14 @@ from registration import signals
|
|||||||
from seaserv import ccnet_threaded_rpc, unset_repo_passwd, is_passwd_set
|
from seaserv import ccnet_threaded_rpc, unset_repo_passwd, is_passwd_set
|
||||||
|
|
||||||
from seahub.profile.models import Profile, DetailedProfile
|
from seahub.profile.models import Profile, DetailedProfile
|
||||||
from seahub.utils import is_valid_username
|
from seahub.utils import is_valid_username, is_user_password_strong
|
||||||
try:
|
try:
|
||||||
from seahub.settings import CLOUD_MODE
|
from seahub.settings import CLOUD_MODE
|
||||||
except ImportError:
|
except ImportError:
|
||||||
CLOUD_MODE = False
|
CLOUD_MODE = False
|
||||||
|
|
||||||
|
from seahub.settings import USER_STRONG_PASSWORD_REQUIRED, \
|
||||||
|
USER_PASSWORD_MIN_LENGTH, USER_PASSWORD_STRENGTH_LEVEL
|
||||||
|
|
||||||
UNUSABLE_PASSWORD = '!' # This will never be a valid hash
|
UNUSABLE_PASSWORD = '!' # This will never be a valid hash
|
||||||
|
|
||||||
@@ -463,40 +465,14 @@ class RegistrationForm(forms.Form):
|
|||||||
def clean_password1(self):
|
def clean_password1(self):
|
||||||
if 'password1' in self.cleaned_data:
|
if 'password1' in self.cleaned_data:
|
||||||
pwd = self.cleaned_data['password1']
|
pwd = self.cleaned_data['password1']
|
||||||
if len(pwd) < 6:
|
|
||||||
raise forms.ValidationError(
|
if USER_STRONG_PASSWORD_REQUIRED is True:
|
||||||
_("Passwords must have at least 6 characters."))
|
if is_user_password_strong(pwd) is True:
|
||||||
|
return pwd
|
||||||
|
else:
|
||||||
|
raise forms.ValidationError(_("%s characters or more, include %s types or more of these: letters(case sensitive), numbers, and symbols") % (USER_PASSWORD_MIN_LENGTH, USER_PASSWORD_STRENGTH_LEVEL))
|
||||||
else:
|
else:
|
||||||
num = 0
|
return pwd
|
||||||
for letter in pwd:
|
|
||||||
# get ascii dec
|
|
||||||
# bitwise OR
|
|
||||||
num |= self.get_char_mode(ord(letter))
|
|
||||||
level = self.caculate_bitwise(num)
|
|
||||||
if level == 1:
|
|
||||||
raise forms.ValidationError(_("Passwords must contain at least 2 types: uppercase letters, lowercase letters, numbers, and symbols"))
|
|
||||||
|
|
||||||
return self.cleaned_data['password1']
|
|
||||||
|
|
||||||
def get_char_mode(self, n):
|
|
||||||
if (n >= 48 and n <= 57): #nums
|
|
||||||
return 1;
|
|
||||||
if (n >= 65 and n <= 90): #uppers
|
|
||||||
return 2;
|
|
||||||
if (n >= 97 and n <= 122): #lowers
|
|
||||||
return 4;
|
|
||||||
else:
|
|
||||||
return 8;
|
|
||||||
|
|
||||||
def caculate_bitwise(self, num):
|
|
||||||
level = 0
|
|
||||||
for i in range(4):
|
|
||||||
# bitwise AND
|
|
||||||
if (num&1):
|
|
||||||
level += 1
|
|
||||||
# Right logical shift
|
|
||||||
num = num >> 1
|
|
||||||
return level
|
|
||||||
|
|
||||||
def clean_password2(self):
|
def clean_password2(self):
|
||||||
"""
|
"""
|
||||||
|
@@ -207,6 +207,18 @@ SHOW_REPO_DOWNLOAD_BUTTON = False
|
|||||||
# mininum length for password of encrypted library
|
# mininum length for password of encrypted library
|
||||||
REPO_PASSWORD_MIN_LENGTH = 8
|
REPO_PASSWORD_MIN_LENGTH = 8
|
||||||
|
|
||||||
|
# mininum length for user's password
|
||||||
|
USER_PASSWORD_MIN_LENGTH = 6
|
||||||
|
|
||||||
|
# LEVEL based on four types of input:
|
||||||
|
# num, upper letter, lower letter, other symbols
|
||||||
|
# '3' means password must have at least 3 types of the above.
|
||||||
|
USER_PASSWORD_STRENGTH_LEVEL = 3
|
||||||
|
|
||||||
|
# default False, only check USER_PASSWORD_MIN_LENGTH
|
||||||
|
# when True, check password strength level, STRONG(or above) is allowed
|
||||||
|
USER_STRONG_PASSWORD_REQUIRED = False
|
||||||
|
|
||||||
# Using server side crypto by default, otherwise, let user choose crypto method.
|
# Using server side crypto by default, otherwise, let user choose crypto method.
|
||||||
FORCE_SERVER_CRYPTO = True
|
FORCE_SERVER_CRYPTO = True
|
||||||
|
|
||||||
|
@@ -7,9 +7,13 @@
|
|||||||
<h2 class="hd">{% trans "Password Modification" %}</h2>
|
<h2 class="hd">{% trans "Password Modification" %}</h2>
|
||||||
<form action="" method="post" class="con">{% csrf_token %}
|
<form action="" method="post" class="con">{% csrf_token %}
|
||||||
<label for="id_old_password">{% trans "Current Password: " %}</label>
|
<label for="id_old_password">{% trans "Current Password: " %}</label>
|
||||||
{{ form.old_password }} {{ form.old_password.errors }}
|
{{ form.old_password }} {{ form.old_password.errors }}
|
||||||
<label for="id_new_password1">{% trans "New Password: " %}</label>
|
<label for="id_new_password1">{% trans "New Password: " %}</label>
|
||||||
{{ form.new_password1 }} {{ form.new_password1.errors }}
|
{% if strong_pwd_required %}
|
||||||
|
<span class="icon-question-sign" title="{% blocktrans %}{{min_len}} characters or more, include {{level}} types or more of these: letters(case sensitive), numbers, and symbols"{% endblocktrans%}></span>
|
||||||
|
{% endif %}
|
||||||
|
{{ form.new_password1 }} {{ form.new_password1.errors }}
|
||||||
|
<div id="pwd_strength"></div>
|
||||||
<label for="id_new_password2">{% trans "Confirm Password: " %}</label>
|
<label for="id_new_password2">{% trans "Confirm Password: " %}</label>
|
||||||
{{ form.new_password2 }} {{ form.new_password2.errors }}
|
{{ form.new_password2 }} {{ form.new_password2.errors }}
|
||||||
|
|
||||||
@@ -22,6 +26,47 @@
|
|||||||
|
|
||||||
{% block extra_script %}
|
{% block extra_script %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$('[type="password"]').addClass('input');
|
$('[type="password"]').addClass('input');
|
||||||
|
|
||||||
|
{% include "snippets/password_strength_js.html" %}
|
||||||
|
|
||||||
|
$("#id_new_password1").keyup(function() {
|
||||||
|
var pwd = $(this).val(),
|
||||||
|
level = getStrengthLevel(pwd);
|
||||||
|
|
||||||
|
if (pwd.length > 0) {
|
||||||
|
showStrength(level);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
$('form').submit(function(){
|
||||||
|
var old_pwd = $.trim($('input[name="old_password"]').val()),
|
||||||
|
pwd1 = $.trim($('input[name="new_password1"]').val()),
|
||||||
|
pwd2 = $.trim($('input[name="new_password2"]').val()),
|
||||||
|
level = getStrengthLevel(pwd1);
|
||||||
|
|
||||||
|
if (!old_pwd) {
|
||||||
|
$('.error').removeClass('hide').html("{% trans "Current password cannot be blank" %}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!pwd1) {
|
||||||
|
$('.error').removeClass('hide').html("{% trans "Password cannot be blank" %}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!pwd2) {
|
||||||
|
$('.error').removeClass('hide').html("{% trans "Please enter the password again" %}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pwd1 != pwd2) {
|
||||||
|
$('.error').removeClass('hide').html("{% trans "Passwords don't match" %}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
{% if strong_pwd_required %}
|
||||||
|
if (level < {{level}}) {
|
||||||
|
$('.error').removeClass('hide').html("{% blocktrans %}{{min_len}} characters or more, include {{level}} types or more of these: letters(case sensitive), numbers, and symbols{% endblocktrans %}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
<label for="id_email">{% trans "Email" %}</label>
|
<label for="id_email">{% trans "Email" %}</label>
|
||||||
{{ form.email }} {{ form.email.errors }}
|
{{ form.email }} {{ form.email.errors }}
|
||||||
<label for="id_password1">{% trans "Password" %}</label> <span class="icon-question-sign" title="{% trans "6 characters or more, include 2 types or more of these: letters(case sensitive), numbers, and symbols" %}"></span>
|
<label for="id_password1">{% trans "Password" %}</label>
|
||||||
|
{% if strong_pwd_required %}
|
||||||
|
<span class="icon-question-sign" title="{% blocktrans %}{{min_len}} characters or more, include {{level}} types or more of these: letters(case sensitive), numbers, and symbols"{% endblocktrans%}></span>
|
||||||
|
{% endif %}
|
||||||
{{ form.password1 }} {{ form.password1.errors }}
|
{{ form.password1 }} {{ form.password1.errors }}
|
||||||
<div id="pwd_strength"></div>
|
<div id="pwd_strength"></div>
|
||||||
<label for="id_password2">{% trans "Confirm Password" %}</label>
|
<label for="id_password2">{% trans "Confirm Password" %}</label>
|
||||||
@@ -40,73 +43,17 @@
|
|||||||
|
|
||||||
{% block extra_script %}
|
{% block extra_script %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
{% include "snippets/password_strength_js.html" %}
|
||||||
|
|
||||||
$("#id_password1").keyup(function() {
|
$("#id_password1").keyup(function() {
|
||||||
var level = getStrengthLevel($(this).val());
|
var pwd = $(this).val(),
|
||||||
showStrength(level);
|
level = getStrengthLevel(pwd);
|
||||||
});
|
|
||||||
|
|
||||||
function getStrengthLevel(pwd) {
|
if (pwd.length > 0) {
|
||||||
var num = 0,
|
showStrength(level);
|
||||||
min_passwd_len = 6;
|
|
||||||
|
|
||||||
if (pwd.length < min_passwd_len) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
for (var i = 0; i < pwd.length; i++) {
|
|
||||||
// return the unicode
|
|
||||||
// bitwise OR
|
|
||||||
num |= getCharMode(pwd.charCodeAt(i));
|
|
||||||
};
|
|
||||||
return calculateBitwise(num);
|
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
|
|
||||||
function getCharMode(n) {
|
|
||||||
if (n >= 48 && n <= 57) // nums
|
|
||||||
return 1;
|
|
||||||
if (n >= 65 && n <= 90) // uppers
|
|
||||||
return 2;
|
|
||||||
if (n >= 97 && n <= 122) // lowers
|
|
||||||
return 4;
|
|
||||||
else
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateBitwise(num) {
|
|
||||||
var level = 0;
|
|
||||||
for (var i = 0; i < 4; i++){
|
|
||||||
// bitwise AND
|
|
||||||
if (num&1) level++;
|
|
||||||
// Right logical shift
|
|
||||||
num>>>=1;
|
|
||||||
}
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showStrength(level) {
|
|
||||||
var strength_ct = $("#pwd_strength");
|
|
||||||
var strength = [
|
|
||||||
"{% trans "too weak" %}",
|
|
||||||
"{% trans "weak" %}",
|
|
||||||
"{% trans "medium" %}",
|
|
||||||
"{% trans "strong" %}"
|
|
||||||
];
|
|
||||||
switch (level) {
|
|
||||||
case 0:
|
|
||||||
strength_ct.html(strength[0]).css("color", '#F00000');
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
strength_ct.html('<span style="background:#db4747;">' + strength[1] + '</span><span>' + strength[2] + '</span><span>' + strength[3] + '</span>');
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
strength_ct.html('<span>' + strength[1] + '</span><span style="background:#fdd64d;">' + strength[2] + '</span><span>' + strength[3] + '</span>');
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
strength_ct.html('<span>' + strength[1] + '</span><span>' + strength[2] + '</span><span style="background:#4aa323;">' + strength[3] + '</span>');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$('form').submit(function(){
|
$('form').submit(function(){
|
||||||
var email = $.trim($('input[name="email"]').val()),
|
var email = $.trim($('input[name="email"]').val()),
|
||||||
@@ -130,14 +77,12 @@ $('form').submit(function(){
|
|||||||
$('.error').removeClass('hide').html("{% trans "Passwords don't match" %}");
|
$('.error').removeClass('hide').html("{% trans "Passwords don't match" %}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pwd1.length < 6) {
|
{% if strong_pwd_required %}
|
||||||
$('.error').removeClass('hide').html("{% trans "Passwords must have at least 6 characters" %}");
|
if (level < {{level}}) {
|
||||||
return false;
|
$('.error').removeClass('hide').html("{% blocktrans %}{{min_len}} characters or more, include {{level}} types or more of these: letters(case sensitive), numbers, and symbols{% endblocktrans %}");
|
||||||
}
|
return false;
|
||||||
if (level <= 2) {
|
}
|
||||||
$('.error').removeClass('hide').html("{% trans "Passwords contain at least 2 types: uppercase letters, lowercase letters, numbers, and symbols" %}");
|
{% endif %}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
62
seahub/templates/snippets/password_strength_js.html
Normal file
62
seahub/templates/snippets/password_strength_js.html
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
function getStrengthLevel(pwd) {
|
||||||
|
var num = 0;
|
||||||
|
|
||||||
|
if (pwd.length < {{min_len}}) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < pwd.length; i++) {
|
||||||
|
// return the unicode
|
||||||
|
// bitwise OR
|
||||||
|
num |= getCharMode(pwd.charCodeAt(i));
|
||||||
|
};
|
||||||
|
return calculateBitwise(num);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCharMode(n) {
|
||||||
|
if (n >= 48 && n <= 57) // nums
|
||||||
|
return 1;
|
||||||
|
if (n >= 65 && n <= 90) // uppers
|
||||||
|
return 2;
|
||||||
|
if (n >= 97 && n <= 122) // lowers
|
||||||
|
return 4;
|
||||||
|
else
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateBitwise(num) {
|
||||||
|
var level = 0;
|
||||||
|
for (var i = 0; i < 4; i++){
|
||||||
|
// bitwise AND
|
||||||
|
if (num&1) level++;
|
||||||
|
// Right logical shift
|
||||||
|
num>>>=1;
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showStrength(level) {
|
||||||
|
var strength_ct = $("#pwd_strength");
|
||||||
|
var strength = [
|
||||||
|
"{% trans "too weak" %}",
|
||||||
|
"{% trans "weak" %}",
|
||||||
|
"{% trans "medium" %}",
|
||||||
|
"{% trans "strong" %}"
|
||||||
|
];
|
||||||
|
switch (level) {
|
||||||
|
case 0:
|
||||||
|
strength_ct.html(strength[0]).css("color", '#F00000');
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
strength_ct.html('<span style="background:#db4747;">' + strength[1] + '</span><span>' + strength[2] + '</span><span>' + strength[3] + '</span>');
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
strength_ct.html('<span>' + strength[1] + '</span><span style="background:#fdd64d;">' + strength[2] + '</span><span>' + strength[3] + '</span>');
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
strength_ct.html('<span>' + strength[1] + '</span><span>' + strength[2] + '</span><span style="background:#4aa323;">' + strength[3] + '</span>');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
@@ -29,7 +29,8 @@ from seaserv import seafserv_rpc, seafserv_threaded_rpc, get_repo, get_commits,\
|
|||||||
list_personal_repos_by_owner, get_group_repos, \
|
list_personal_repos_by_owner, get_group_repos, \
|
||||||
list_inner_pub_repos, CCNET_CONF_PATH, SERVICE_URL
|
list_inner_pub_repos, CCNET_CONF_PATH, SERVICE_URL
|
||||||
import seahub.settings
|
import seahub.settings
|
||||||
from seahub.settings import SITE_NAME, MEDIA_URL, LOGO_PATH
|
from seahub.settings import SITE_NAME, MEDIA_URL, LOGO_PATH, \
|
||||||
|
USER_PASSWORD_STRENGTH_LEVEL, USER_PASSWORD_MIN_LENGTH
|
||||||
try:
|
try:
|
||||||
from seahub.settings import EVENTS_CONFIG_FILE
|
from seahub.settings import EVENTS_CONFIG_FILE
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -945,3 +946,51 @@ def user_traffic_over_limit(username):
|
|||||||
|
|
||||||
month_traffic = stat['file_view'] + stat['file_download'] + stat['dir_download']
|
month_traffic = stat['file_view'] + stat['file_download'] + stat['dir_download']
|
||||||
return True if month_traffic >= traffic_limit else False
|
return True if month_traffic >= traffic_limit else False
|
||||||
|
|
||||||
|
def is_user_password_strong(password):
|
||||||
|
"""Return ``True`` if user's password is STRONG, otherwise ``False``.
|
||||||
|
STRONG means password has at least USER_PASSWORD_STRENGTH_LEVEL(3) types of the bellow:
|
||||||
|
num, upper letter, lower letter, other symbols
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(password) < USER_PASSWORD_MIN_LENGTH:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
num = 0
|
||||||
|
for letter in password:
|
||||||
|
# get ascii dec
|
||||||
|
# bitwise OR
|
||||||
|
num |= get_char_mode(ord(letter))
|
||||||
|
|
||||||
|
if calculate_bitwise(num) < USER_PASSWORD_STRENGTH_LEVEL:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_char_mode(n):
|
||||||
|
"""Return different num according to the type of given letter:
|
||||||
|
'1': num,
|
||||||
|
'2': upper_letter,
|
||||||
|
'4': lower_letter,
|
||||||
|
'8': other symbols
|
||||||
|
"""
|
||||||
|
if (n >= 48 and n <= 57): #nums
|
||||||
|
return 1;
|
||||||
|
if (n >= 65 and n <= 90): #uppers
|
||||||
|
return 2;
|
||||||
|
if (n >= 97 and n <= 122): #lowers
|
||||||
|
return 4;
|
||||||
|
else:
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
def calculate_bitwise(num):
|
||||||
|
"""Return different level according to the given num:
|
||||||
|
"""
|
||||||
|
level = 0
|
||||||
|
for i in range(4):
|
||||||
|
# bitwise AND
|
||||||
|
if (num&1):
|
||||||
|
level += 1
|
||||||
|
# Right logical shift
|
||||||
|
num = num >> 1
|
||||||
|
return level
|
||||||
|
@@ -9,6 +9,8 @@ from django.shortcuts import render_to_response
|
|||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
|
|
||||||
from registration.backends import get_backend
|
from registration.backends import get_backend
|
||||||
|
from seahub.settings import USER_PASSWORD_MIN_LENGTH, \
|
||||||
|
USER_STRONG_PASSWORD_REQUIRED, USER_PASSWORD_STRENGTH_LEVEL
|
||||||
|
|
||||||
def activate(request, backend,
|
def activate(request, backend,
|
||||||
template_name='registration/activate.html',
|
template_name='registration/activate.html',
|
||||||
@@ -204,5 +206,8 @@ def register(request, backend, success_url=None, form_class=None,
|
|||||||
form = form_class(initial={'email': src})
|
form = form_class(initial={'email': src})
|
||||||
|
|
||||||
return render_to_response(template_name,
|
return render_to_response(template_name,
|
||||||
{ 'form': form },
|
{ 'form': form,
|
||||||
context_instance=context)
|
'min_len': USER_PASSWORD_MIN_LENGTH,
|
||||||
|
'strong_pwd_required': USER_STRONG_PASSWORD_REQUIRED,
|
||||||
|
'level': USER_PASSWORD_STRENGTH_LEVEL,
|
||||||
|
}, context_instance=context)
|
||||||
|
Reference in New Issue
Block a user