요구 정책
- 8자리 이상
- 영문, 숫자, 특수문자 포함
구현 방식
- DRF가 아닌 Pure Django에서 구현했습니다.
- validators.py에 원하는 검사를 구현하고, forms.py에 validator를 추가했습니다.
구현
settings.py
AUTH_PASSWORD_VALIDATORS = [
{
'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': 'users.validators.CustomPasswordValidator', # 추가
},
]
VALIDATORS를 추가하였습다. 구현한 validators.py에서도 기존의 validator도 사용하기 때문에 기존 validator 및에 추가하였습니다.
validators.py
from django.core.exceptions import ValidationError
from django.contrib.auth.password_validation import validate_password
import re
class CustomPasswordValidator:
def __call__(self, value): # 1)
try:
validate_password(value)
except ValidationError as e:
raise ValidationError(str(e))
def validate(self, password, user=None):
"""비밀번호 유효성 검사"""
if len(password) < 8:
raise ValidationError("비밀번호는 8자리 이상이어야 합니다.")
if not re.search(r"[a-zA-Z]", password):
raise ValidationError("비밀번호는 하나 이상의 영문이 포함되어야 합니다.")
if not re.search(r"\d", password):
raise ValidationError("비밀번호는 하나 이상의 숫자가 포함되어야 합니다.")
if not re.search(r"[!@#$%^&*()]", password):
raise ValidationError(
"비밀번호는 적어도 하나 이상의 특수문자(!@#$%^&*())가 포함되어야 합니다."
)
def get_help_text(self): # 2)
return "비밀번호는 8자리 이상이며 영문, 숫자, 특수문자((!@#$%^&*()))를 포함해야 합니다."
이렇게 구현했습니다.
위에처럼 정규 표현식이 아닌 아래처럼 일반 파이썬 문으로도 구현이 가능합니다.
if not any(char.isalpha() for char in value):
raise forms.ValidationError("비밀번호는 하나 이상의 영문이 포함되어야 합니다.")
if not any(char.isalpha() for char in value):
raise forms.ValidationError("비밀번호는 하나 이상의 숫자가 포함되어야 합니다.")
if not any(char in "!@#$%^&*()" for char in value):
raise forms.ValidationError("비밀번호는 적어도 하나 이상의 특수문자((!@#$%^&*()))가 포함되어야 합니다.")
1)
이 클래스 CustomPasswordValidator
는 callable 객체를 정의합니다. 클래스의 인스턴스를 함수로 호출할 수 있는 __call__
메서드를 구현합니다. 이 경우 'CustomPasswordValidator' 인스턴스는 암호 값을 인수로 사용하여 호출할 수 있습니다.
__call__
메서드 내에서 validate_password
함수가 호출되어 django가 기본으로 제공하는 암호 유효성 검사를 실행합니다. 유효성 검사 오류가 발생하면 오류 메시지와 함께 ValidationError
가 발생합니다.
다시 말하면, __call__
이 메소드는 SignUpForm
클래스의 validators=[CustomPasswordValidator()]
행과 같이 클래스의 인스턴스가 함수로 호출될 때 호출됩니다. CustomPasswordValidator()
가 호출되면 __call__
메서드가 트리거되고 validate_password()
함수를 호출합니다.
또한 CustomPasswordValidator
클래스는 validate
메서드도 정의합니다. 이 메서드는 인스턴스가 함수로 호출될 때(__call__
메서드와 같이) 자동으로 실행되지 않지만 validate_password()
가 수행하는 것 이상의 추가 암호 유효성 검사 규칙을 제공합니다. 이러한 추가 규칙은 비밀번호의 길이와 영문, 숫자 및 특수 문자를 포함하는지 여부를 확인합니다.
따라서 SignUpForm
클래스에서 CustomPasswordValidator()
를 유효성 검사기로 사용하면 validate_password()
함수와 validate()
메서드가 모두 실행되어 비밀번호를 검증합니다.
2)
get_help_text
메서드는 암호 요구 사항에 대한 정보를 제공하는 도움말 텍스트를 반환합니다. 이는 예상되는 암호 형식에 대한 추가 정보를 사용자에게 표시하는 데 유용할 수 있습니다.
forms.py
from django import forms
from .validators import CustomPasswordValidator
class SignUpForm(forms.Form):
... 생략 ...
password = forms.CharField(
widget=forms.PasswordInput,
validators=[CustomPasswordValidator()],
)
... 생략 ...
이렇게 import 해서 사용합니다.
'Python > Django' 카테고리의 다른 글
FK 관계를 설정하는 방법 (0) | 2023.06.30 |
---|---|
(Django) reverse와 reverse_lazy 차이 (0) | 2023.06.23 |
UniqueConstraint 사용 예시 (0) | 2023.04.05 |
Django Model에서의 Meta 클래스 (0) | 2023.04.04 |
Django의 admin 패널에서 모델 등록하는 두가지 방법 (0) | 2023.03.16 |