django.contrib.auth의authenticate 함수 원본 분석

6462 단어 원본 코드django
인용문
django는 사용자의 로그인과 권한 수여에 사용되는 기본auth시스템을 제공하고 일정한 확장성을 제공합니다. 개발자가 여러 개의 검증 백엔드를 스스로 정의할 수 있도록 합니다. 모든 검증 백엔드는 authenticate 함수를 실현하고 None이나 User 대상을 되돌려야 합니다.
기본 백그라운드는django입니다.contrib.auth.backends.ModelBackend, 이 백엔드는 사용자 이름과 비밀번호를 통해 사용자 인증을 하고 settings로 합니다.AUTH_USER_MODEL을 모델로 사용합니다.그러나 실제 개발에서 모두가 사용자 이름과 같은 모델을 고정적으로 사용하여 검증하지 않을 것이라고 믿는다. 예를 들어 서로 다른 역할은 서로 다른 모델을 검증하는 데이터 원천으로 하고 어떤 역할은 핸드폰으로 로그인하며 어떤 역할은 메일로 로그인한다.
그렇다면 여러 개의 검증 백엔드가 존재할 때django는 어떻게 통일된 인터페이스를 만들어 서로 다른 백엔드 검증을 합니까?
authenticate 함수 분석
소스:
def authenticate(**credentials):
    """ If the given credentials are valid, return a User object. """
    for backend, backend_path in _get_backends(return_tuples=True):
        try:
            inspect.getcallargs(backend.authenticate, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            continue

        try:
            user = backend.authenticate(**credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be allowed in at all.
            break
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path
        return user

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials))

**credentials
우선authenticate 함수가 받아들이는 매개 변수를 볼 수 있습니다. 이것은authenticate 함수가 키워드만 받아들이고 위치는 허용하지 않는다는 것을 말합니다.따라서 authenticate 함수를 사용할 때 수고를 덜기 위해 위치에서 참조를 하지 않도록 주의하십시오.
# This will fail
user = authenticate('username', 'password')

# This will success
user = authenticate(username='username', password='password')

inspect.getcallargs(func, *args, **kwargs)
ppect 모듈은 파이톤의 공식 표준 모듈로 이 모듈은 파이톤의 자성 기능을 일정한 봉인을 한다.그중에 인스펙트.getcallargs는args와kwargs 이 매개 변수가func에서 요구하는 매개 변수와 일치하는지 검사합니다. 일치하지 않으면 매개 변수 사전을 되돌려줍니다. 일치하지 않으면 raise TypeError입니다.간단한 예를 들다.Python에서 다음과 같은 함수를 정의한다고 가정합니다.
import inspect

def test_func(arg1, arg2, *args, **kwargs):
    pass

# this will raise TypeError
inspect.getcallargs(test_func, a=1, b=2, c=3)
# TypeError: test_func() missing 2 required positional arguments: 'arg1' and 'arg2'

# this will ok
inspect.getcallargs(test_func, 1, 2, 3, a=1, b=2, c=3)
# {'kwargs': {'b': 2, 'c': 3, 'a': 1}, 'arg2': 2, 'args': (3,), 'arg1': 1}

장면 적용
인스펙트를 통해서.getcallargs의 매개 변수 필터 기능은 서로 다른 백엔드의authenticate 함수 매개 변수를 설정하면 첫 번째 단계에서 서로 다른 역할의 백엔드 선택을 실현할 수 있습니다.
만약에 세 가지 캐릭터가 있다고 가정하면 캐릭터 1은 사용자 이름으로 로그인하고 캐릭터 2는 핸드폰으로 로그인하며 캐릭터 3은 핸드폰이나 메일로 로그인하면 어떻게 인스펙트를 통과할 것인가.getcallargs는 적합한 백엔드를 선택하십시오.authenticate는요?
def role3_authenticate(role3_phone=None, role3_email=None, password=None):
    print("role1 authentication.")

def role2_authenticate(role2_phone=None, password=None):
    print("role2 authenticate.")

def role1_authenticate(role1_name=None, password=None):
    print("role2 authenticate.")

methods = [role1_authenticate, role2_authenticate, role3_authenticate]


def authenticate(**credentials):
    for backend in methods:
        try:
            inspect.getcallargs(backend, **credentials)
        except TypeError:
            print("error")
            continue

        backend(**credentials)
        print("end")
        break

**kwargs를 추가하면 모든 authenticate가 TypeError를 일으키지 않습니다. 나머지 매개 변수는 기본 매개 변수를 설정했기 때문에 필요하면 이전의 매개 변수는 위치 참조를 사용합니다.
signal
만약 사용자가 로그인에 성공하지 못했다면, authenticate는 사용자가 로그인에 성공하지 못한 신호를 보냈고, 개발자는 이 신호를 받아들이는recevier를 스스로 정의할 수 있습니다.django signal에 관해서는 필자가 나중에 상세하게 이야기할 것이다.

좋은 웹페이지 즐겨찾기