Skip to content

Commit

Permalink
feat(password validation): 全面支持自定义密码强度
Browse files Browse the repository at this point in the history
  • Loading branch information
Oo-RR-oO committed Jul 13, 2020
1 parent 19a703c commit 2b3421a
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 27 deletions.
17 changes: 9 additions & 8 deletions oneid/password_validation.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
"""
自定义规则校验集合
自定义密码复杂度校验集合
"""
import re

from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from rest_framework.exceptions import ValidationError

PASSWORD_COMPLEXITY = getattr(settings, "PASSWORD_COMPLEXITY", None)


# pylint: disable=useless-object-inheritance
# pylint: disable=too-many-branches
class _ComplexityValidator(object):
"""自定义密码强度校验规则"""
message = _("必须更加复杂 (%s)")
"""自定义密码复杂度校验规则"""
message = _("密码必须更加复杂 (%s)")
code = "password_complexity"

def __init__(self, complexities):
Expand Down Expand Up @@ -55,22 +55,23 @@ def __call__(self, value):
errors.append(_("%(SPECIAL)s 个及以上的特殊字符") % self.complexities)
if len(words) < self.complexities.get("WORDS", 0):
errors.append(_("%(WORDS)s 个及以上不同的单词") % self.complexities)

if len(value) < self.complexities.get("LENGTH", 0):
errors.append(_("%(LENGTH)s 长度及以上的密码") % self.complexities)
if errors:
raise ValidationError(self.message % (_(u'必须包含 ') + u', '.join(errors), ), code=self.code)


_complexity = _ComplexityValidator(PASSWORD_COMPLEXITY)
_COMPLEXITY = _ComplexityValidator(PASSWORD_COMPLEXITY)


# pylint: disable=missing-function-docstring
class ComplexityValidator(object):
class ComplexityValidator:
"""
Wrapper for validators.ComplexityValidator which is compatible
with the Django 1.9+ password validation API
"""
def __init__(self):
self.validator = _complexity
self.validator = _COMPLEXITY

# pylint: disable=no-self-use
def get_help_text(self):
Expand Down
39 changes: 23 additions & 16 deletions oneid/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,17 +148,23 @@
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
# {
# 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
# 'OPTIONS': {
# 'min_length': 8,
# },
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
# },
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
'NAME': 'oneid.password_validation.ComplexityValidator',
},
]

Expand Down Expand Up @@ -316,12 +322,13 @@
# 密码复杂度规则
# 值表示至少需包含的相应元素的个数,默认全部为0
PASSWORD_COMPLEXITY = {
"UPPER": 1, # 包含大写字母的个数
"LOWER": 1, # 包含小写字母的个数
"LETTERS": 1, # 包含大写和小写字母的个数
"DIGITS": 1, # 包含数字的个数
"SPECIAL": 1, # 包含特殊字符的个数 (不是字母数字、空格或标点字符)
"WORDS": 1, # 包含单词的个数 (由空格或标点分隔的字母数字序列)
"LENGTH": 0, # 密码的长度
"UPPER": 0, # 包含大写字母的个数
"LOWER": 0, # 包含小写字母的个数
"LETTERS": 0, # 包含大写和小写字母的个数
"DIGITS": 0, # 包含数字的个数
"SPECIAL": 0, # 包含特殊字符的个数 (不是字母数字、空格或标点字符)
"WORDS": 0, # 包含单词的个数 (由空格或标点分隔的字母数字序列)
}

if os.path.exists(os.path.join(BASE_DIR, 'settings_local.py')):
Expand Down
13 changes: 13 additions & 0 deletions siteapi/v1/serializers/ucenter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'''
serializers for ucenter
'''
from django.contrib.auth.password_validation import validate_password
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from common.django.drf.serializer import DynamicFieldsModelSerializer
Expand Down Expand Up @@ -104,6 +105,12 @@ def update(self, instance, validated_data):
user.save(update_fields=['require_reset_password'])
return user

@staticmethod
def validate_new_password(value):
"""密码复杂度检验"""
validate_password(value)
return value


class UserRegisterSerializer(DynamicFieldsModelSerializer):
'''
Expand Down Expand Up @@ -170,6 +177,12 @@ def create(self, validated_data):
cli.set_user_password(user, password)
return user

@staticmethod
def validate_password(value):
"""密码复杂度检验"""
validate_password(value)
return value


class UserAlterMobileSerializer(serializers.Serializer): # pylint: disable=abstract-method
'''
Expand Down
8 changes: 7 additions & 1 deletion siteapi/v1/serializers/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
'''
serializers for user
'''

from django.contrib.auth.password_validation import validate_password
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

Expand Down Expand Up @@ -498,3 +498,9 @@ def update(self, instance, validated_data):
instance.require_reset_password = require_reset_password
instance.save(update_fields=['require_reset_password'])
return instance

@staticmethod
def validate_password(value):
"""密码复杂度检验"""
validate_password(value)
return value
3 changes: 2 additions & 1 deletion siteapi/v1/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
- UserDept
'''
# pylint: disable=too-many-lines

from rest_framework import generics, status, views
from rest_framework.response import Response
from rest_framework.exceptions import (
Expand All @@ -17,6 +16,7 @@
from rest_framework.permissions import IsAuthenticated, SAFE_METHODS
from django.db import transaction
from django.db.models import Q
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ObjectDoesNotExist, FieldDoesNotExist
from oneid_meta.models import User, Group, Dept, GroupMember, UserPerm
from oneid.permissions import (
Expand Down Expand Up @@ -228,6 +228,7 @@ def create(self, request, *args, **kwargs): # pylint: disable=unused-argument
password = user_info.pop('password', None)
user = cli.create_user(user_info)
if password:
validate_password(password)
cli.set_user_password(user, password)
user.origin = 1 # 管理员添加
user.save()
Expand Down
2 changes: 1 addition & 1 deletion uwsgi.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ processes = %(%k + 1)
thunder-lock = true
harakiri = 30

listen = 65535
;listen = 65535

disable-logging = true

0 comments on commit 2b3421a

Please sign in to comment.