# Django 2.1.8.dev20190330215650 documentation

# Django 인증 커스터마이징하기

Django에 포함된 인증은 대부분의 일반적인 경우에서 충분히 좋습니다. 그렇지만 원한다면 Django 기본 인증에서 벗어나셔도 됩니다. 당신의 프로젝트에서 인증에 대한 사항을 커스터마이징하기 위해서는 먼저 시스템이 제공해주는 것 중에 어떤 것이 확장 가능하고 어떤 것이 대체 가능한지 알아야 합니다. 이 문서는 어떻게 인증 시스템을 커스터마이징 할 수 있는지에 대해서 자세히 다룹니다.

:ref:`인증 백엔드 <authentication-backends>`는 user model에 저장된 username과 password이 Django의 디폴트가 아닌 다른 서비스에서 인증되어야 할 경우를 위한 확장가능한 시스템을 제공합니다.

독자는 자신의 모델에 Django의 인증 시스템을 통해 확인할 수 있는 :ref:`맞춤 권한 <custom-permissions>`을 줄 수 있습니다.

독자는 디폴트 `User` 모델을 :ref:`확장 <extending-user>`하거나 완전히 맞춤화된 모델로 :ref:`대체 <auth-custom-user>`할 수 있습니다.

## 다른 인증 소스들

또 다른 인증 소스가 필요한 순간이 있을 수 있습니다 -- 즉, username과 password 또는 인증 메소드의 또 다른 소스.

예를 들어 독자의 회사가 모든 직원의 username과 password를 저장하는 LDAP 설정을 이미 가지고 있을 수 있습니다. 만약 사용자가 계정을 LDAP와 Django기반의 애플리케이션에 분리했다면 그건 네트워크 관리자와 사용자 모두에게 곤란할 것입니다.

따라서 이런 상황을 다루기 위해 Django 인증 시스템은 독자가 다른 인증 소스에 플러그인 할 수 있게 해줍니다. 독자는 Django의 디폴트 데이터베이스 기반 스키마를 오버라이드할 수 있습니다. 또는 독자는 다른 시스템과 협력관계로 디폴트 시스템을 사용할 수 있습니다.

Django에 포함된 인증 백엔드에 관한 정보는 :ref:`인증 백엔드 참조 <authentication-backends-reference>`에서 볼 수 있습니다.

### 인증 백엔드 명세하기

비하인드로 Django는 인증을 확인하는 "인증 백엔드" 리스트를 유지하고 있습니다. 누군가 :func:`django.contrib.auth.authenticate()`를 호출하면 -- :ref:`사용자 로그인 방법 <how-to-log-a-user-in>`에서 서술한 것처럼 -- Django는 모든 인증 백엔드를 거쳐 인증을 시도합니다. 만약 가장 처음의 인증 메소드가 실패하면 Django는 두번째 것을 시도하고 모든 백엔드가 시도될 때까지 반복합니다.

사용하는 인증 백엔드 리스트는 `AUTHENTICATION_BACKENDS` 설정에 명세됩니다. 이것은 인증하는 방법을 알고 있는 Python 클래스를 가리키는 Python 경로 이름 리스트 이어야 합니다. 이 클래스들은 독자의 Python 경로의 어디에나 있을 수 있습니다.

디폴트로 `AUTHENTICATION_BACKENDS` 는 다음과 같이 설정됩니다:

    ['django.contrib.auth.backends.ModelBackend']

그것은 Django 사용자 데이터베이스를 확인하고 내장된 권한을 질의하는 기본 인증 백엔드입니다. 이 백엔드는 임의의 속도 제한 메커니즘을 통한 무차별 대입 공경에 대한 보호는 제공하지 않습니다. 독자는 맞춤 인증 백엔드에서 스스로의 속도 제한 메커니즘을 구현하거나 대부분의 웹 서버에서 제공되는 메커니즘을 사용하셔야 합니다.

`AUTHENTICATION_BACKENDS` 의 순서는 중요합니다. 만약 같은 username과 password가 참인 여러 개의 백엔드가 있으면 Django는 첫번째 참인 곳에서 처리를 멈출 것입니다.

만약 백엔드가 `PermissionDenied` 예외를 발생시키면, 인증은 즉시 실패할 것입니다. Django는 뒤따르는 백엔드는 확인하지 않습니다.

주석

사용자는 한번 인증되고 나면 Django는 어떤 백엔드가 사용자 인증에 사용되었는지 사용자 세션에 저장하고 현재 인증된 사용자의 접근이 필요할 때 세션이 지속되는 동안은 같은 백엔드를 재사용 합니다. 이것은 효과적으로 인증 소스가 세션 단위를 기본으로 캐쉬되는 것을 의미합니다. 만약 독자가 :setting:`AUTHENTICATION_BACKENDS`를 변경하면 사용자가 다른 메소드를 사용해 재인증을 해야할 필요가 있다면 세션 데이터를 비워야 합니다. 간단한 방법은 ``Session.objects.all().delete()``를 실행하는 것입니다.

### 인증 백엔드 작성하기

인증 백엔드는 두 가지 필수 메소드를 구현하는 클래스입니다: 인증 메소드 와 관련된 선택적 권한 집합 뿐만 아니라 `get_user(user_id)` 와 `authenticate(request, **credentials)`.

get_user`` 메소드는 `user_id` 를 반환하는데, 이것은 username, 데이터베이스 ID 또는 무엇이든 될 수 있습니다. 하지만 user object 의 primary key 이어야 하며 사용자 객체를 반환합니다.

`authenticate` 메소드는 `request` 인자와 키워드 인자로 자격증명을 취합니다. 대부분의 경우 이것은 다음과 같이 보일 것입니다:

    class MyBackend:
        def authenticate(self, request, username=None, password=None):
            # Check the username/password and return a user.
            ...

하지만 이것은 또한 다음과 같이 토큰을 인증하는 것일 수 있습니다:

    class MyBackend:
        def authenticate(self, request, token=None):
            # Check the token and return a user.
            ...

어느 것이든 `authenticate()` 는 자격 증명을 확인하고 이 자격 증명이 참인 경우 이 자격 증명과 매치하는 사용자 객체를 리턴해야 합니다. 만약 참이 아니라면 ``None``을 리턴해야 합니다.

`request` 는 django.http.HttpRequest 라는 Class 이고 만일 django.contrib.auth.authenticate 함수 (백엔드로 그걸 전달하는) 가 제공되지 않으면 `None` 일 수 있습니다.

Django 관리자는 Django 사용자 객체 와 단단히 결합되어 있습니다. 관리자를 다루는 가장 좋은 방법은 Django `User` 객체를 독자의 백엔드 에 존재하는 각 사용자로 생성하는 것입니다. (e.g., 독자의 LDAP 디렉토리 에서 외부 SQL 데이터베이스 등) 사전에 스크립트를 작성해서 하거나 `authenticate` 메소드가 사용자가 로그인한 첫 순간에 할 수 있습니다.

여기에 여러분의 `settings.py` 파일에 정의된 username 과 password 로 인증하여 사용자가 첫 번째로 인증할 때 Django `User` 객체를 생성하는 백엔드 예제가 있습니다:

    from django.conf import settings
    from django.contrib.auth.hashers import check_password
    from django.contrib.auth.models import User

    class SettingsBackend:
        """
        Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.

        Use the login name and a hash of the password. For example:

        ADMIN_LOGIN = 'admin'
        ADMIN_PASSWORD = 'pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M='
        """

        def authenticate(self, request, username=None, password=None):
            login_valid = (settings.ADMIN_LOGIN == username)
            pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
            if login_valid and pwd_valid:
                try:
                    user = User.objects.get(username=username)
                except User.DoesNotExist:
                    # Create a new user. There's no need to set a password
                    # because only the password from settings.py is checked.
                    user = User(username=username)
                    user.is_staff = True
                    user.is_superuser = True
                    user.save()
                return user
            return None

        def get_user(self, user_id):
            try:
                return User.objects.get(pk=user_id)
            except User.DoesNotExist:
                return None

### 맞춤 백엔드 에서 인증 다루기

맞춤 인증 백엔드는 스스로 권한을 제공할 수 있다.

사용자 모델은 권한 조회 함수(`get_group_permissions()`, `get_all_permissions()`, `has_perm()`, and `has_module_perms()`) 를 이 함수를 구현하는 인증 백엔드로 위임할 것입니다.

사용자에게 주어진 권한은 모든 백엔드에서 반환되는 전체 권한의 상위 집합일 것입니다. 즉, Django 는 하나의 백엔드를 주는 사용자에게 권한을 줍니다.

만약 백엔드가 `has_perm()` 이나 `has_module_perms()` 에서 `PermissionDenied` 예외가 일어나면 , 인증은 즉시 실패하고 Django 는 뒤따르는 백엔드를 확인하지 않을 것입니다.

위의 단순한 백엔드는 꽤 간단하게 매직 관리자를 위한 권한을 구현할 수 있습니다:

    class SettingsBackend:
        ...
        def has_perm(self, user_obj, perm, obj=None):
            return user_obj.username == settings.ADMIN_LOGIN

위의 예제에서 접근을 허가받은 사용자들에게 완전한 권한을 부여합니다. 연관된 `django.contrib.auth.models.User` 함수에서 주어진 같은 인자이지만 백엔드 인증 함수는 모두 인자로 익명 사용자일 수도 있는 사용자 객체를 받는다는 것을 명심하세요.

완전한 인증 구현은 django/contrib/auth/backends.py`_기본 백엔드이며 ``auth_permission` 테이블을 주로 질의하는 `ModelBackend` 클래스에서 찾을 수 있습니다. 만약 독자가 맞춤 행위를 백엔드 API의 부분만 제공하길 원한다면 맞춤 백엔드로 완전한 API를 구현하는 대신 Python 상속과 `ModelBackend` 서브클래스의 이점을 취할 수 있습니다.

#### 익명 사용자를 위한 인증

익명 사용자는 인증되지 않은 사용자입니다. 즉 그들은 참인 인증 상세를 제공하지 않습니다. 하지만 그것이 꼭 어떤 것을 하는데 권한을 부여받지 않음을 의미하는 것은 아닙니다. 대부분의 기초 수준에서 많은 웹사이트들이 익명 사용자에게 대부분의 사이트를 둘러볼 것을 허가하고 익명 댓글을 포스팅하는 것을 허가합니다.

Django의 권한 프레임워크는 익명 사용자를 위한 권한을 저장하는 장소를 가지고 있지 않습니다. 하지만 인증 백엔드에서 전달되는 사용자 객체는 백엔드가 익명 사용자의 맞춤 인증 행동을 명세할 수 있는 `django.contrib.auth.models.AnonymousUser` 객체일 수 있습니다. 이것은 특히 모든 인증 질문을 예를 들면 익명 접근을 제어할 설정을 필요로 하기 보다는 인증 백엔드에 위임할 수 있는 재사용 가능한 앱의 저자에게 유용합니다.

#### 비활성 사용자를 위한 인증

비활성 사용자는 `is_active` 필드가 `False` 로 설정되어 있는 사람입니다. `ModelBackend` 와 `RemoteUserBackend` 인증 백엔드는 이 사용자들이 인증되는 것을 막습니다. 만약 맞춤 사용자 모델이 `is_active` 필드를 가지고 있지 않다면, 모든 사용자는 인증이 허락될 것 입니다.

만약 비활성 사용자가 인증하는 것을 허락하고자 하면, 독자는 `AllowAllUsersModelBackend` 나 `AllowAllUsersRemoteUserBackend` 를 사용할 수 있습니다.

권한 시스템에서 익명 사용자를 위한 지원은 비활성 인증된 사용자가 할 수는 없지만 익명 사용자는 가능한 시나리오를 포함합니다.

여러분의 백엔드 권한 메소드에서 사용자의 `is_active` 속성을 테스트 하는 것을 잊지 마세요.

#### 객체 권한 다루기

Django의 권한 프레임워크는 비록 코어에 구현은 되어 있지 않지만 객체 권한에 기반를 두고 있습니다. 즉 객체 권한을 확인하면 항상 `False``나 빈 리스트를 반환할 것입니다 (확인이 수행됨에 따라서). 인증 백엔드는 인증 메소드와 관련된 각 객체에 ``obj` 와 `user_obj` 키워드 파라미터를 받고 적합한 객체 수준 권한을 반환할 수 있습니다.

## 맞춤 권한

주어진 모델 객체를 위한 맞춤 권한을 생성하기 위해서 `permissions` 모델 메타 속성 을 사용합니다.

이 예제 `Task` 모델은 두 가지 맞춤 권한, 즉 애플리케이션 사용자가 `Task` 인스턴스를 가지고 할 수 있는 것과 할 수 없는 것을 정의합니다.

    class Task(models.Model):
        ...
        class Meta:
            permissions = (
                ("change_task_status", "Can change the status of tasks"),
                ("close_task", "Can remove a task by setting its status as closed"),
            )

이것이 하는 유일한 일은 `manage.py migrate <migrate>`(:data:`~django.db.models.signals.post_migrate` 시그널에 연결된 권한을 생성하는 함수)를 실행할 때 추가적인 권한을 생성하는 것입니다. 당신의 코드는 애플리케이션의 기능에 사용자가 접근(작업의 상태를 변경하거나 작업을 종료)을 시도할 때 이러한 권한들의 값을 검사할 책임이 있습니다. 위의 예에 이어, 다음은 사용자가 작업을 닫아도 되는지 확인합니다.

    user.has_perm('app.close_task')

## 기존 `User` 모델 확장하기

독자 스스로의 모델을 대체하지 않고 기본 `User` 모델을 확장시키는 데 두 가지 방법이 있습니다. 만약 여러분이 하고자 하는 변경이 순수히 행동적이고 데이터베이스에 저장되는 것의 변화는 필요하지 않다면 독자는 `User` 에 기반한 프록시 모델 을 생성할 수 있습니다. 이것은 기본 정렬, 맞춤 매니저 또는 맞춤 모델 메소드를 포함해서 프록시 모델에서 제안된 기능을 허용합니다.

만약 독자가 `User` 에 관련된 정보를 저장하길 원한다면 `OneToOneField` 를 추가적인 정보를 위한 필드를 포함하는 모델로 사용할 수 있습니다. 이 일대일 모델은 사이트 사용자에 대한 비인증 관련 정보를 저장할 수도 있기 때문에 종종 프로필 모델로 불립니다. 예를 들어 독자는 Employee 모델을 생성할 수도 있습니다:

    from django.contrib.auth.models import User

    class Employee(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        department = models.CharField(max_length=100)

User와 Employee 모델을 가지는 Employee Fred Smith가 있다고 가정하면 여러분은 Django의 표준 연관 모델 관례에 따라 관련된 정보에 접근할 수 있습니다:

    >>> u = User.objects.get(username='fsmith')
    >>> freds_department = u.employee.department

프로필 모델의 필드를 관리자 사용자 페이지에 추가하기 위해선 `InlineModelAdmin` 를 독자 앱의 `admin.py``에 정의합니다. (예로 우리는 :class:`~django.contrib.admin.StackedInline`를 사용할 것입니다.) 그리고 :class:`~django.contrib.auth.models.User` 클래스로 등록된 ``UserAdmin` 클래스에 더합니다.

    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from django.contrib.auth.models import User

    from my_user_profile_app.models import Employee

    # Define an inline admin descriptor for Employee model
    # which acts a bit like a singleton
    class EmployeeInline(admin.StackedInline):
        model = Employee
        can_delete = False
        verbose_name_plural = 'employee'

    # Define a new User admin
    class UserAdmin(BaseUserAdmin):
        inlines = (EmployeeInline,)

    # Re-register UserAdmin
    admin.site.unregister(User)
    admin.site.register(User, UserAdmin)

이 프로필 모델은 어떤 방식으로든 특별하지 않습니다. - 이것은 단지 사용자 모델과 일대일 링크를 가지기 위한 Django 모델입니다. 이와 같이 프로필 모델은 사용자가 생성될 때 스스로 생성되지 않고 :attr:`django.db.models.signals.post_save`이 생성 또는 관련 모델을 업데이트하기 위해 적절히 사용될 될 수 있습니다.

관련 모델을 사용하면 추가적인 질의나 관련 데이터를 검색할 수 있습니다. 독자의 필요에 따라 관련 필드를 포함하는 맞춤 사용자 모델은 더 나은 선택이 될 수 있습니다. 하지만 프로젝트 앱에서 기본 사용자 모델의 관계를 유지시키면 추가 데이터베이스 로드를 정당화 할 수 있습니다.

## 맞춤 `User` 모델 대체하기

몇몇 종류의 프로젝트는 Django의 빌트인 `User` 모델이 항상 적절하진 않은 인증 요구사항을 가지고 있을 수 있습니다. 예를 들어 어떤 사이트에서는 사용자 이름 대신 이메일 주소를 인증 토큰을 사용하는 것이 더 적합할 수 있습니다.

Django는 독자가 맞춤 모델을 참조하는 `AUTH_USER_MODEL` 설정값을 제공함으로써 기본 사용자 모델을 오버라이드하도록 할 수 있습니다:

    AUTH_USER_MODEL = 'myapp.MyUser'

이 점선 쌍은 Django 앱의 이름이자 (`INSTALLED_APPS` 에 반드시 있을) 독자가 사용자 모델로 사용하기를 원하는 Django 모델의 이름입니다.

### 프로젝트를 시작할 때 맞춤 사용자 모델 사용하기

만약 독자가 새로운 프로젝트를 시작한다면 기본 `User` 모델이 독자에게 충분하더라도 맞춤 사용자 모델을 설정할 것을 강력히 추천합니다.이 모델은 기본 사용자 모델과 똑같이 행동하지만 만약 필요한 일이 생긴다면 이후에 모델을 맞추화할 수 있습니다:

    from django.contrib.auth.models import AbstractUser

    class User(AbstractUser):
        pass

모델에 `AUTH_USER_MODEL` 을 가리키는 것을 잊지마세요. 이 작업은 마이그레이션을 생성하거나 `manage.py migrate` 를 처음으로 실행시키기 전에 합니다.

또한 앱의 ``admin.py``에 모델을 등록합니다:

    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin
    from .models import User

    admin.site.register(User, UserAdmin)

### 프로젝트 중간에 맞춤 사용자 모델 변경하기

데이터베이스 테이블을 생성한 뒤 `AUTH_USER_MODEL` 를 변경하는 것은 예를 들면 변경이 외래 키와 다대다 관계에 영향을 주기 때문에 상당히 더 어렵습니다.

이 변경은 자동으로는 불가능하고 수동으로 독자의 스키마를 수정하고 데이터를 이전 사용자 테이블에서 옮기고 몇 가지 마이그레이션을 어떻게해서든 수동으로 적용시킬 필요성이 있습니다. 단계들의 개요는 #25313 에서 보실 수 있습니다.

교환가능한 모델을 위한 Django의 동적 의존성 기능의 한계로 `AUTH_USER_MODEL` 로부터 참조된 모델은 앱의 첫 번째 마이그레이션에서 생성되어야만 합니다. (보통 `0001_initial` 로 불리는) 그렇지 않으면 독자는 의존성 이슈를 가지게 될 것입니다.

또한, Django는 동적 의존성으로 인한 의존성 루프를 자동으로 해소해주지 않으므로 마이그레이션을 수행할 때 `CircularDependencyError`가 발생할 수 있습니다. 이 오류가 발생하면 사용자 모델에 의존하는 모델들을 두 번째 마이그레이션으로 옮김으로써 루프를 해소해야 합니다(일반적으로 어떻게 이뤄지는지 보고 싶다면 서로에 대해 `ForeignKey`를 갖는 두 개의 일반적인 모델을 만들고 `makemigrations`가 순환 의존성을 어떻게 다루는지 볼 수 있습니다).

### 재사용 가능한 앱과 `AUTH_USER_MODEL`

재사용 가능한 앱은 맞춤 사용자 모델을 구현하면 안 됩니다. 하나의 프로젝트는 많은 앱을 사용할 수 있고 맞춤 사용자 모델이 구현된 재사용 가능한 앱은 두 개가 동시에 사용될 수 없습니다. 만약 독자가 앱마다 사용자 정보를 저장할 필요가 있다면 아래에서 처럼 `ForeignKey` 또는 `OneToOneField` 를 `settings.AUTH_USER_MODEL` 로 사용하세요.

### `User` 모델 참조하기

만약 독자가 `User` 를 직접 참조한다면 (예를 들어 외래 키로 참조하듯이), `AUTH_USER_MODEL` 설정이 다른 사용자 모델로 변경된 프로젝트에서는 코드가 동작하지 않을 것입니다.

`get_user_model`()

  Instead of referring to `User` directly, you should reference the user model using `django.contrib.auth.get_user_model()`. This method will return the currently active user model -- the custom user model if one is specified, or `User` otherwise.

  독자가 외래 키나 다대다 관계를 사용자 모델에 정의할 때 독자는 `AUTH_USER_MODEL` 설정을 사용하는 맞춤 모델을 명세해야 합니다. 예를 들어:

      from django.conf import settings
      from django.db import models

      class Article(models.Model):
          author = models.ForeignKey(
              settings.AUTH_USER_MODEL,
              on_delete=models.CASCADE,
          )

  사용자 모델에서 받은 시그널을 연결할 때 독자는 `AUTH_USER_MODEL` 설정을 사용해 맞춤 모델을 명세해야 합니다. 예를 들면:

      from django.conf import settings
      from django.db.models.signals import post_save

      def post_save_receiver(sender, instance, created, **kwargs):
          pass

      post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)

  일반적으로 임포트 시간에 실행되는 코드의 `AUTH_USER_MODEL` 설정으로 사용자 모델을 참조하는 것이 가장 쉬운 방법입니다. 하지만 Django가 모델을 임포팅하는 동안에 `get_user_model()``를 호출하는 것도 가능한 벙법이므로 독자는 이런 식으로 ``models.ForeignKey(get_user_model(), ...)` 사용할 수 있습니다.

  만약 독자의 앱이 여러 개의 사용자 모델로 테스트 되고, 예를 들어 `@override_settings(AUTH_USER_MODEL=...)` 를 사용해서, 독자가 모듈 레벨의 변수에서``get_user_model()``의 결과를 캐시한다면 독자는 캐시를 지우기 위해 `setting_changed` 시그널을 들을 필요가 있을 수 있습니다. 예를 들면:

      from django.apps import apps
      from django.contrib.auth import get_user_model
      from django.core.signals import setting_changed
      from django.dispatch import receiver

      @receiver(setting_changed)
      def user_model_swapped(**kwargs):
          if kwargs['setting'] == 'AUTH_USER_MODEL':
              apps.clear_cache()
              from myapp import some_module
              some_module.UserModel = get_user_model()

### 맞춤 사용자 모델 명세하기

모델 설계 고려사항

독자의 맞춤 사용자 모델에서 인증과 직접적으로 관련있지 않은 정보를 다루기 전에 잘 생각해 보세요.

사용자 모델과 관계있는 모델에 앱의 특정한 사용자 정보를 저장하는 것이 더 나을 수도 있습니다. 각각의 앱이 다른 앱과 충돌할 위험없이 사용자 데이터 요구사항을 명확히 할 수 있습니다. 한편 관련된 정보를 조회하는 질의는 성능에 영향을 줄 수 있는 데이터베이스 조인을 수반할 것입니다.

Django는 독자의 맞춤 사용자 모델이 최소한의 요구사항을 만날 것을 예상합니다.

만약 독자가 기본 인증 백엔드를 사용한다면 모델은 인증 목적을 위해 사용될 수 있는 하나의 고유한 필드를 가져야합니다. 이 필드는 사용자 이름, 이메일 주소, 또는 다른 고유한 속성도 가능합니다. 고유하지 않은 사용자 이름 필드는 독자가 이것을 지원할 수 있는 맞춤 인증 백엔드를 사용한다면 허용됩니다.

올바른 맞춤 사용자 모델을 만드는 가장 쉬운 방법은 `AbstractBaseUser` 를 상속하는 것입니다. `AbstractBaseUser` 은 해쉬 비밀번호와 토큰화된 비밀번호 재설정을 포함해서 사용자 모델의 핵심적인 구현을 제공합니다. 독자는 몇 가지 키 구현을 상세하게 제공해야 합니다.

class `models.``CustomUser`
  `USERNAME_FIELD`

    사용자 모델에서 고유한 식별자로서 사용되는 필드명을 기술하는 문자열. 이것은 사용자명이 될 수도 있지만, 이메일 주소가 될 수도 있고 그외의 고유한 식별자가 될 수도 있습니다. 이 필드는 고유하지 않은 사용자명을 지원하는 맞춤 인증 백엔드를 사용하지 않는 한, 반드시 고유해야 합니다(정의에서 `unique=True`로 설정).

    다음 예에서 `identifier` 필드가 식별 필드로 사용됩니다.

        class MyUser(AbstractBaseUser):
            identifier = models.CharField(max_length=40, unique=True)
            ...
            USERNAME_FIELD = 'identifier'

  `EMAIL_FIELD`

    "User" model 에서 이메일 필드를 이름을 묘사하는 스트링. 이 값은 "models.AbstractBaseUser.get_email_field_name" 라는 메서드로 얻을수 있습니다.

  `REQUIRED_FIELDS`

    djadmin ( = django-admin ) 의 createsuperuser 명령으로 user 를 만들때 입력대기 (prompted) 되는 필드 이름들 목록. user 는 이들 필드들이 입력 되도록 합니다. 그것은 다음과 같은 필드들을 포함 시킵니다. 속성이 django.db.models.Field.blank 는 "False" 혹은 "undefined" 로 , 그리고 아마도 다른 필드들은 user 가 생성될때 상호작동 방식으로 입력 되도록 포함 될 수도 있습니다.

    예를 들어, 여기에 값이 제공되어야 하는 두개의 필드 - 생년월일, 키 - 를 갖는 User Model 에 대한 부분적인 정의(definition) 를 하였습니다.

        class MyUser(AbstractBaseUser):
            ...
            date_of_birth = models.DateField()
            height = models.FloatField()
            ...
            REQUIRED_FIELDS = ['date_of_birth', 'height']

    주석

    요구되는 필드들(Required Fields) 는 여러분의 user model 에서 요구되는 필드의 모두 포함합니다만 "USERNAME_FIELD" 혹은 "Password" 필드는 제외합니다. 이들은 항상 입력이 되도록 하기 때문입니다.

  `is_active`

    A boolean attribute that indicates whether the user is considered "active". This attribute is provided as an attribute on `AbstractBaseUser` defaulting to `True`. How you choose to implement it will depend on the details of your chosen auth backends. See the documentation of the `is_active attribute on the built-in user model` for details.

  `get_full_name`()

    Optional. A longer formal identifier for the user such as their full name. If implemented, this appears alongside the username in an object's history in `django.contrib.admin`.

  `get_short_name`()

    Optional. A short, informal identifier for the user such as their first name. If implemented, this replaces the username in the greeting to the user in the header of `django.contrib.admin`.

  Changed in Django 2.0:

  In older versions, subclasses are required to implement `get_short_name()` and `get_full_name()` as `AbstractBaseUser` has implementations that raise `NotImplementedError`.

  Importing `AbstractBaseUser`

  `AbstractBaseUser` and `BaseUserManager` are importable from `django.contrib.auth.base_user` so that they can be imported without including `django.contrib.auth` in `INSTALLED_APPS`.

The following attributes and methods are available on any subclass of `AbstractBaseUser`:

class `models.``AbstractBaseUser`
  `get_username`()

    Returns the value of the field nominated by `USERNAME_FIELD`.

  `clean`()

    Normalizes the username by calling `normalize_username()`. If you override this method, be sure to call `super()` to retain the normalization.

  classmethod `get_email_field_name`()

    Returns the name of the email field specified by the `EMAIL_FIELD` attribute. Defaults to `'email'` if `EMAIL_FIELD` isn't specified.

  classmethod `normalize_username`(username)

    Applies NFKC Unicode normalization to usernames so that visually identical characters with different Unicode code points are considered identical.

  `is_authenticated`

    Read-only attribute which is always `True` (as opposed to `AnonymousUser.is_authenticated` which is always `False`). This is a way to tell if the user has been authenticated. This does not imply any permissions and doesn't check if the user is active or has a valid session. Even though normally you will check this attribute on `request.user` to find out whether it has been populated by the `AuthenticationMiddleware` (representing the currently logged-in user), you should know this attribute is `True` for any `User` instance.

  `is_anonymous`

    Read-only attribute which is always `False`. This is a way of differentiating `User` and `AnonymousUser` objects. Generally, you should prefer using `is_authenticated` to this attribute.

  `set_password`(raw_password)

    Sets the user's password to the given raw string, taking care of the password hashing. Doesn't save the `AbstractBaseUser` object.

    When the raw_password is `None`, the password will be set to an unusable password, as if `set_unusable_password()` were used.

  `check_password`(raw_password)

    Returns `True` if the given raw string is the correct password for the user. (This takes care of the password hashing in making the comparison.)

  `set_unusable_password`()

    Marks the user as having no password set. This isn't the same as having a blank string for a password. `check_password()` for this user will never return `True`. Doesn't save the `AbstractBaseUser` object.

    You may need this if authentication for your application takes place against an existing external source such as an LDAP directory.

  `has_usable_password`()

    Returns `False` if `set_unusable_password()` has been called for this user.

  `get_session_auth_hash`()

    Returns an HMAC of the password field. Used for Session invalidation on password change.

`AbstractUser` subclasses `AbstractBaseUser`:

class `models.``AbstractUser`
  `clean`()

    Normalizes the email by calling `BaseUserManager.normalize_email()`. If you override this method, be sure to call `super()` to retain the normalization.

### Writing a manager for a custom user model

You should also define a custom manager for your user model. If your user model defines `username`, `email`, `is_staff`, `is_active`, `is_superuser`, `last_login`, and `date_joined` fields the same as Django's default user, you can just install Django's `UserManager`; however, if your user model defines different fields, you'll need to define a custom manager that extends `BaseUserManager` providing two additional methods:

class `models.``CustomUserManager`
  `create_user`(*username_field*, password=None, **other_fields)

    The prototype of `create_user()` should accept the username field, plus all required fields as arguments. For example, if your user model uses `email` as the username field, and has `date_of_birth` as a required field, then `create_user` should be defined as:

        def create_user(self, email, date_of_birth, password=None):
            # create user here
            ...

  `create_superuser`(*username_field*, password, **other_fields)

    The prototype of `create_superuser()` should accept the username field, plus all required fields as arguments. For example, if your user model uses `email` as the username field, and has `date_of_birth` as a required field, then `create_superuser` should be defined as:

        def create_superuser(self, email, date_of_birth, password):
            # create superuser here
            ...

    Unlike `create_user()`, `create_superuser()` must require the caller to provide a password.

For a `ForeignKey` in `USERNAME_FIELD` or `REQUIRED_FIELDS`, these methods receive the value of the `to_field` (the `primary_key` by default) of an existing instance.

`BaseUserManager` provides the following utility methods:

class `models.``BaseUserManager`
  classmethod `normalize_email`(email)

    Normalizes email addresses by lowercasing the domain portion of the email address.

  `get_by_natural_key`(username)

    Retrieves a user instance using the contents of the field nominated by `USERNAME_FIELD`.

  `make_random_password`(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')

    Returns a random password with the given length and given string of allowed characters. Note that the default value of `allowed_chars` doesn't contain letters that can cause user confusion, including:

    - `i`, `l`, `I`, and `1` (lowercase letter i, lowercase letter L, uppercase letter i, and the number one)
    - `o`, `O`, and `0` (lowercase letter o, uppercase letter o, and zero)

### Extending Django's default `User`

If you're entirely happy with Django's `User` model and you just want to add some additional profile information, you could simply subclass `django.contrib.auth.models.AbstractUser` and add your custom profile fields, although we'd recommend a separate model as described in the "Model design considerations" note of 맞춤 사용자 모델 명세하기. `AbstractUser` provides the full implementation of the default `User` as an abstract model.

### Custom users and the built-in auth forms

Django's built-in forms and views make certain assumptions about the user model that they are working with.

The following forms are compatible with any subclass of `AbstractBaseUser`:

- `AuthenticationForm`: Uses the username field specified by `USERNAME_FIELD`.
- `SetPasswordForm`
- `PasswordChangeForm`
- `AdminPasswordChangeForm`

The following forms make assumptions about the user model and can be used as-is if those assumptions are met:

- `PasswordResetForm`: Assumes that the user model has a field that stores the user's email address with the name returned by `get_email_field_name()` (`email` by default) that can be used to identify the user and a boolean field named `is_active` to prevent password resets for inactive users.

Finally, the following forms are tied to `User` and need to be rewritten or extended to work with a custom user model:

- `UserCreationForm`
- `UserChangeForm`

만일 커스텀 유저 모델이 간단한 "AbstractUser" 의 subclass 라면 이 방법으로 forms 를 확장 시킬 수 있습니다.

    from django.contrib.auth.forms import UserCreationForm
    from myapp.models import CustomUser

    class CustomUserCreationForm(UserCreationForm):

        class Meta(UserCreationForm.Meta):
            model = CustomUser
            fields = UserCreationForm.Meta.fields + ('custom_field',)

### 커스텀 User 와 django.contrib.admin 모듈

커스텀 User Model 이 admin 에서도 작동 되길 원하면 추가적인 속성과 매서드를 정의해야 합니다. 이들 매서드들은 Admin 으로 하여금 admin content 에 그 User Model 을Access 할 수 있게 합니다.

class `models.``CustomUser`

`is_staff`

  그 user 가 admin site 에 접근 가능하다면 "True" 를 반환합니다

`is_active`

  그 user 가 지금 현재 "active" 하다면 "True" 를 반환합니다

`has_perm(perm, obj=None):`

  Returns `True` if the user has the named permission. If `obj` is provided, the permission needs to be checked against a specific object instance.

`has_module_perms(app_label):`

  Returns `True` if the user has permission to access models in the given app.

You will also need to register your custom user model with the admin. If your custom user model extends `django.contrib.auth.models.AbstractUser`, you can use Django's existing `django.contrib.auth.admin.UserAdmin` class. However, if your user model extends `AbstractBaseUser`, you'll need to define a custom `ModelAdmin` class. It may be possible to subclass the default `django.contrib.auth.admin.UserAdmin`; however, you'll need to override any of the definitions that refer to fields on `django.contrib.auth.models.AbstractUser` that aren't on your custom user class.

### Custom users and permissions

To make it easy to include Django's permission framework into your own user class, Django provides `PermissionsMixin`. This is an abstract model you can include in the class hierarchy for your user model, giving you all the methods and database fields necessary to support Django's permission model.

`PermissionsMixin` provides the following methods and attributes:

class `models.``PermissionsMixin`
  `is_superuser`

    Boolean. Designates that this user has all permissions without explicitly assigning them.

  `get_group_permissions`(obj=None)

    Returns a set of permission strings that the user has, through their groups.

    If `obj` is passed in, only returns the group permissions for this specific object.

  `get_all_permissions`(obj=None)

    Returns a set of permission strings that the user has, both through group and user permissions.

    If `obj` is passed in, only returns the permissions for this specific object.

  `has_perm`(perm, obj=None)

    Returns `True` if the user has the specified permission, where `perm` is in the format `"<app label>.<permission codename>"` (see permissions). If `User.is_active` and `is_superuser` are both `True`, this method always returns `True`.

    If `obj` is passed in, this method won't check for a permission for the model, but for this specific object.

  `has_perms`(perm_list, obj=None)

    Returns `True` if the user has each of the specified permissions, where each perm is in the format `"<app label>.<permission codename>"`. If `User.is_active` and `is_superuser` are both `True`, this method always returns `True`.

    If `obj` is passed in, this method won't check for permissions for the model, but for the specific object.

  `has_module_perms`(package_name)

    Returns `True` if the user has any permissions in the given package (the Django app label). If `User.is_active` and `is_superuser` are both `True`, this method always returns `True`.

`PermissionsMixin` and `ModelBackend`

If you don't include the `PermissionsMixin`, you must ensure you don't invoke the permissions methods on `ModelBackend`. `ModelBackend` assumes that certain fields are available on your user model. If your user model doesn't provide those fields, you'll receive database errors when you check permissions.

### Custom users and proxy models

One limitation of custom user models is that installing a custom user model will break any proxy model extending `User`. Proxy models must be based on a concrete base class; by defining a custom user model, you remove the ability of Django to reliably identify the base class.

If your project uses proxy models, you must either modify the proxy to extend the user model that's in use in your project, or merge your proxy's behavior into your `User` subclass.

### A full example

Here is an example of an admin-compliant custom user app. This user model uses an email address as the username, and has a required date of birth; it provides no permission checking, beyond a simple `admin` flag on the user account. This model would be compatible with all the built-in auth forms and views, except for the user creation forms. This example illustrates how most of the components work together, but is not intended to be copied directly into projects for production use.

This code would all live in a `models.py` file for a custom authentication app:

    from django.db import models
    from django.contrib.auth.models import (
        BaseUserManager, AbstractBaseUser
    )

    class MyUserManager(BaseUserManager):
        def create_user(self, email, date_of_birth, password=None):
            """
            Creates and saves a User with the given email, date of
            birth and password.
            """
            if not email:
                raise ValueError('Users must have an email address')

            user = self.model(
                email=self.normalize_email(email),
                date_of_birth=date_of_birth,
            )

            user.set_password(password)
            user.save(using=self._db)
            return user

        def create_superuser(self, email, date_of_birth, password):
            """
            Creates and saves a superuser with the given email, date of
            birth and password.
            """
            user = self.create_user(
                email,
                password=password,
                date_of_birth=date_of_birth,
            )
            user.is_admin = True
            user.save(using=self._db)
            return user

    class MyUser(AbstractBaseUser):
        email = models.EmailField(
            verbose_name='email address',
            max_length=255,
            unique=True,
        )
        date_of_birth = models.DateField()
        is_active = models.BooleanField(default=True)
        is_admin = models.BooleanField(default=False)

        objects = MyUserManager()

        USERNAME_FIELD = 'email'
        REQUIRED_FIELDS = ['date_of_birth']

        def __str__(self):
            return self.email

        def has_perm(self, perm, obj=None):
            "Does the user have a specific permission?"
            # Simplest possible answer: Yes, always
            return True

        def has_module_perms(self, app_label):
            "Does the user have permissions to view the app `app_label`?"
            # Simplest possible answer: Yes, always
            return True

        @property
        def is_staff(self):
            "Is the user a member of staff?"
            # Simplest possible answer: All admins are staff
            return self.is_admin

Then, to register this custom user model with Django's admin, the following code would be required in the app's `admin.py` file:

    from django import forms
    from django.contrib import admin
    from django.contrib.auth.models import Group
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from django.contrib.auth.forms import ReadOnlyPasswordHashField

    from customauth.models import MyUser

    class UserCreationForm(forms.ModelForm):
        """A form for creating new users. Includes all the required
        fields, plus a repeated password."""
        password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
        password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

        class Meta:
            model = MyUser
            fields = ('email', 'date_of_birth')

        def clean_password2(self):
            # Check that the two password entries match
            password1 = self.cleaned_data.get("password1")
            password2 = self.cleaned_data.get("password2")
            if password1 and password2 and password1 != password2:
                raise forms.ValidationError("Passwords don't match")
            return password2

        def save(self, commit=True):
            # Save the provided password in hashed format
            user = super().save(commit=False)
            user.set_password(self.cleaned_data["password1"])
            if commit:
                user.save()
            return user

    class UserChangeForm(forms.ModelForm):
        """A form for updating users. Includes all the fields on
        the user, but replaces the password field with admin's
        password hash display field.
        """
        password = ReadOnlyPasswordHashField()

        class Meta:
            model = MyUser
            fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')

        def clean_password(self):
            # Regardless of what the user provides, return the initial value.
            # This is done here, rather than on the field, because the
            # field does not have access to the initial value
            return self.initial["password"]

    class UserAdmin(BaseUserAdmin):
        # The forms to add and change user instances
        form = UserChangeForm
        add_form = UserCreationForm

        # The fields to be used in displaying the User model.
        # These override the definitions on the base UserAdmin
        # that reference specific fields on auth.User.
        list_display = ('email', 'date_of_birth', 'is_admin')
        list_filter = ('is_admin',)
        fieldsets = (
            (None, {'fields': ('email', 'password')}),
            ('Personal info', {'fields': ('date_of_birth',)}),
            ('Permissions', {'fields': ('is_admin',)}),
        )
        # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
        # overrides get_fieldsets to use this attribute when creating a user.
        add_fieldsets = (
            (None, {
                'classes': ('wide',),
                'fields': ('email', 'date_of_birth', 'password1', 'password2')}
            ),
        )
        search_fields = ('email',)
        ordering = ('email',)
        filter_horizontal = ()

    # Now register the new UserAdmin...
    admin.site.register(MyUser, UserAdmin)
    # ... and, since we're not using Django's built-in permissions,
    # unregister the Group model from admin.
    admin.site.unregister(Group)

Finally, specify the custom model as the default user model for your project using the `AUTH_USER_MODEL` setting in your `settings.py`:

    AUTH_USER_MODEL = 'customauth.MyUser'