---
title: "Django 인증 시스템을 사용"
version: 4.0
locale: ko
source: https://docs.djangoproject.com/ko/4.0/topics/auth/default/
canonical: https://djangodocs.dev/ko/4.0/topics/auth/default/
---
# Django 인증 시스템을 사용

This document explains the usage of Django’s authentication system in its
default configuration. This configuration has evolved to serve the most common
project needs, handling a reasonably wide range of tasks, and has a careful
implementation of passwords and permissions. For projects where authentication
needs differ from the default, Django supports extensive [extension and
customization](/ko/4.0/topics/auth/customizing/) of authentication.

Django authentication provides both authentication and authorization together
and is generally referred to as the authentication system, as these features
are somewhat coupled.

## `사용자` 객체

[`User`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User) objects are the core of the
authentication system. They typically represent the people interacting with
your site and are used to enable things like restricting access, registering
user profiles, associating content with creators etc. Only one class of user
exists in Django’s authentication framework, i.e., [`'superusers'`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.is_superuser) or admin [`'staff'`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.is_staff) users are just user objects with
special attributes set, not different classes of user objects.

디폴트 사용자의 주요 속성은 :

- [`username`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.username)
- [`password`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.password)
- [`email`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.email)
- [`first_name`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.first_name)
- [`last_name`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.last_name)

See the [`full API documentation`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User) for
full reference, the documentation that follows is more task oriented.

### 사용자 생성하기

사용자 생성을 하는 가장 직관적인 방법은 [`create_user()`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.UserManager.create_user) 헬퍼함수:: 를 사용하는 것입니다.

```
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

# At this point, user is a User object that has already been saved
# to the database. You can continue to change its attributes
# if you want to change other fields.
>>> user.last_name = 'Lennon'
>>> user.save()
```

만약 Django admin 이 설치되어 있다면, :ref:\` 사용자를 상호작용적으로 추가\<auth-admin\>\` 할 수 있다.

### Superusers 생성하기

[`createsuperuser`](/ko/4.0/ref/django-admin/#django-admin-createsuperuser) 명령어를:: 이용해 superusers 추가하기

```
$ python manage.py createsuperuser --username=joe --email=joe@example.com
```

당신은 프롬프트를 통해 패스워드 입력을  해야할 것 입니다. 패스워드를 입력한 뒤, 사용자가 바로 생성될 것입니다. 만약 [`--username`](/ko/4.0/ref/django-admin/#cmdoption-createsuperuser-username) or [`--email`](/ko/4.0/ref/django-admin/#cmdoption-createsuperuser-email) 옵션들을 사용하지 않으면, 이들의 값을 위해 프롬프트로 물어볼 것입니다.

### 패스워드 변경하기

Django 는 사용자 모델에 원본 패스워드(일반 텍스트)를 저장하지 않고, 오직 해쉬만 저장합니다. (디테일하게 보기 [비밀번호 조작하기 문서](/ko/4.0/topics/auth/passwords/) ). 이로 인해, 사용자의 패스워드 속성을 직접적으로 조작하려 시도하지 마십시오. 이는 사용자 생성을 위해 헬퍼 함수를 사용하는 이유입니다.

사용자의 패스워드를 변경하기 위해, 여러 옵션이 있습니다.

[`manage.py changepassword *username*`](/ko/4.0/ref/django-admin/#django-admin-changepassword) offers a method
of changing a user’s password from the command line. It prompts you to
change the password of a given user which you must enter twice. If
they both match, the new password will be changed immediately. If you
do not supply a user, the command will attempt to change the password
whose username matches the current system user.

You can also change a password programmatically, using
[`set_password()`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.set_password):

```pycon
>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='john')
>>> u.set_password('new password')
>>> u.save()
```

If you have the Django admin installed, you can also change user’s passwords
on the [authentication system’s admin pages](#auth-admin).

Django also provides [views](#built-in-auth-views) and [forms](#built-in-auth-forms) that may be used to allow users to change their own
passwords.

Changing a user’s password will log out all their sessions. See
[패스워드 변경시 세션 무효화](#session-invalidation-on-password-change) for details.

### 사용자 인증하기

#### `authenticate(request=None, **credentials)`

Use [`authenticate()`](#django.contrib.auth.authenticate) to verify a set of
credentials. It takes credentials as keyword arguments, `username` and
`password` for the default case, checks them against each
[authentication backend](/ko/4.0/topics/auth/customizing/#authentication-backends), and returns a
[`User`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User) object if the credentials are
valid for a backend. If the credentials aren’t valid for any backend or if
a backend raises [`PermissionDenied`](/ko/4.0/ref/exceptions/#django.core.exceptions.PermissionDenied), it
returns `None`. For example:

```
from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # A backend authenticated the credentials
else:
    # No backend authenticated the credentials
```

`request` is an optional [`HttpRequest`](/ko/4.0/ref/request-response/#django.http.HttpRequest) which is
passed on the `authenticate()` method of the authentication backends.

> **Note**
>
> This is a low level way to authenticate a set of credentials; for
> example, it’s used by the
> [`RemoteUserMiddleware`](/ko/4.0/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware). Unless
> you are writing your own authentication system, you probably won’t use
> this. Rather if you’re looking for a way to login a user, use the
> [`LoginView`](#django.contrib.auth.views.LoginView).

## 권한과 인증

Django에는 권한 시스템이 내장되어 있다. 해당 권한 시스템은 특정 사용자 및 사용자 그룹에 권한을 할당하는 방법을 제공한다.

그것은 Django 관리자 사이트에 사용 되지만 당신만의 소스코드에 사용할 수도 있다.

Django 관리자 사이트는 권한을 다음과 같이 사용한다:

- 객체 보기에 대한 액세스 권한은 해당 객체 유형에 대한 “보기” 또는 “변경” 권한이 있는 사용자로 제한된다.
- “추가” 양식을 보고 객체를 추가할 수 있는 액세스 권한은 해당 객체 유형에 대한 “추가” 권한이 있는 사용자로 제한된다.
- 변경 목록 보기, “변경” 양식 보기 및 객체 변경에 대한 액세스 권한은 해당 객체 유형에 대한 “변경” 권한이 있는 사용자로 제한된다.
- 객체를 삭제할 수 있는 액세스 권한은 해당 객체 유형에 대해 “삭제” 권한이 있는 사용자로 제한된다.

권한은 객체 유형별로 설정할 수 있을 뿐만 아니라 특정 객체 인스턴스별로도 설정할 수 있다.
[`ModelAdmin`](/ko/4.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin) 클래스별 [`has_view_permission()`](/ko/4.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_view_permission), [`has_add_permission()`](/ko/4.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_add_permission), [`has_change_permission()`](/ko/4.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_change_permission), [`has_delete_permission()`](/ko/4.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_delete_permission)  method를 사용하여 동일한 유형의 다른 객체 인스턴스에 대한 권한을 커스터마이즈 할 수 있다.

[`User`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User) 객체에는 groups\`\`와 user\_permissions\`\`라는 두 개의 다대다 필드가 있다. [`User`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User) 객체는 다른 [Django model](/ko/4.0/topics/db/models/)::와 동일한 방식으로 관련된 객체에 액세스할 수 있다.

```
myuser.groups.set([group_list])
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions.set([permission_list])
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()
```

### 디폴트 권한

django.contrib.auth\`\`가 [`INSTALLED_APPS`](/ko/4.0/ref/settings/#std-setting-INSTALLED_APPS) 설정에 나열되면 설치된 애플리케이션 중 하나에 정의된 각 Django 모델에 대해 네 가지 기본 권한인 추가, 변경, 삭제 및 보기가 생성되도록 한다.

이 권한은 다음을 실행할 때 생성된다. [`manage.py migrate`](/ko/4.0/ref/django-admin/#django-admin-migrate); ```INSTALLED_APPS`에 ``django.contrib.auth``를 추가한 후 ``migrate``를 처음 실행할 때, 기본 권한은 이전에 설치된 모든 모델과 해당 시점에 설치되는 모든 새 모델에 대해 생성된다. 이후 :djadmin:`manage.py migrate <migrate>`를 실행할 때마다 새 모델에 대한 기본 권한을 생성한다. (권한을 생성하는 함수는 :data:`~django.db.models.signals.post_migrate``` 신호에 연결됨). .

[`app_label`](/ko/4.0/ref/models/options/#django.db.models.Options.app_label) `foo` 와 Bar\`\`라는 모델이 있는 애플리케이션이 있다고 가정하고 기본 권한을 테스트하려면 다음을 사용해야 한다:

- add: `user.has_perm('foo.add_bar')`
- change: `user.has_perm('foo.change_bar')`
- delete: `user.has_perm('foo.delete_bar')`
- view: `user.has_perm('foo.view_bar')`

[`Permission`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.Permission) 모델은 직접 액세스하는 경우가 거의 없다.

### 그룹

[`django.contrib.auth.models.Group`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.Group) 모델은 사용자를 분류하는 일반적인 방법이므로 해당 사용자에게 권한이나 다른 레이블을 적용할 수 있다. 사용자는 여러 그룹에 속할 수 있다.

그룹의 사용자는 자동으로 해당 그룹에 부여된 권한을 갖는다. 예를 들어 `Site editors` 그룹에 `can_edit_home_page` 권한이 있는 경우 해당 그룹의 모든 사용자는 해당 권한을 갖게 됩니다.

권한 외에도 그룹은 사용자를 분류하여 레이블이나 확장된 기능을 제공하는 편리한 방법이다. 예를 들어 `'Special users'` 그룹을 만들고 사이트의 회원 전용 부분에 대한 액세스 권한을 부여하거나 회원 전용 이메일 메시지를 보내는 코드를 작성할 수 있다.

### 프로그래밍적으로 권한 추가하기

custom permissions \<custom-permissions\>\`은 모델의 \`\`Meta\` 클래스 내에서 정의할 수 있지만 권한을 직접 생성할 수도 있다. 예를 들어 `myapp`::에서 `BlogPost` 모델에 대한 `can_publish` 권한을 생성할 수 있다.

```
from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
    codename='can_publish',
    name='Can Publish Posts',
    content_type=content_type,
)
```

그런 다음 `user_permissions` 속성을 통해 권한을 ``` User`에 할당하거나 또는 ``permissions` ``` 속성을 통해 :class:~django.contrib.auth.models.Group\`에 할당할 수 있다.

> **프록시 모델은 자체 컨텐츠 유형이 필요합니다**
>
> permissions for a proxy model \<proxy-models-permissions-topic\>\`을 생성하려면 \`\`for\_concrete\_model=False\`\`를 :meth:.ContentTypeManager.get\_for\_model\`에 전달하여 적절한 ContentType\`::을 가져온다.
>
> ```
> content_type = ContentType.objects.get_for_model(BlogPostProxy, for_concrete_model=False)
> ```

### 권한 캐싱

:class:~django.contrib.auth.backends.ModelBackend\`는 권한 확인을 위해 가져와야 하는 처음 사용자 객체에 대한 권한을 캐시한다. 권한은 일반적으로 추가된 직후 확인되지 않기 때문에 일반적으로 요청-응답 주기에 적합하다(예: 관리자에서). 예를 들어 테스트나 보기에서 권한을 추가하고 즉시 확인하는 경우 가장 쉬운 솔루션은 데이터베이스에서 사용자를 다시 가져오는 것이다. 예를 들어:

```
from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404

from myapp.models import BlogPost

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
    user.has_perm('myapp.change_blogpost')

    content_type = ContentType.objects.get_for_model(BlogPost)
    permission = Permission.objects.get(
        codename='change_blogpost',
        content_type=content_type,
    )
    user.user_permissions.add(permission)

    # Checking the cached permission set
    user.has_perm('myapp.change_blogpost')  # False

    # Request new instance of User
    # Be aware that user.refresh_from_db() won't clear the cache.
    user = get_object_or_404(User, pk=user_id)

    # Permission cache is repopulated from the database
    user.has_perm('myapp.change_blogpost')  # True

    ...
```

### 프록시 모델 (Proxy Model )

프록시 모델은 실제 모델과 정확히 같은 방식으로 작동한다. 권한은 프록시 모델의 자체 콘텐츠 유형을 사용하여 생성된다. 프록시 모델은 하위 클래스로 분류되는 실제 모델의 권한을 상속하지 않는다.

```
class Person(models.Model):
    class Meta:
        permissions = [('can_eat_pizzas', 'Can eat pizzas')]

class Student(Person):
    class Meta:
        proxy = True
        permissions = [('can_deliver_pizzas', 'Can deliver pizzas')]

>>> # Fetch the content type for the proxy model.
>>> content_type = ContentType.objects.get_for_model(Student, for_concrete_model=False)
>>> student_permissions = Permission.objects.filter(content_type=content_type)
>>> [p.codename for p in student_permissions]
['add_student', 'change_student', 'delete_student', 'view_student',
'can_deliver_pizzas']
>>> for permission in student_permissions:
...     user.user_permissions.add(permission)
>>> user.has_perm('app.add_person')
False
>>> user.has_perm('app.can_eat_pizzas')
False
>>> user.has_perms(('app.add_student', 'app.can_deliver_pizzas'))
True
```

## 웹 요청에서 인증

Django는 :doc:sessions\`와 미들웨어를 사용하여 인증 시스템을 :class:request objects \<django.http.HttpRequest\>\`에 연결한다.

이들은 현재 사용자를 나타내는 모든 요청에 대해 [`request.user`](/ko/4.0/ref/request-response/#django.http.HttpRequest.user) 속성을 제공한다. 현재 사용자가 로그인하지 않은 경우 이 속성은 :class:~django.contrib.auth.models.AnonymousUser\`의 인스턴스로 설정되고, 그렇지 않으면 :class:~django.contrib.auth.models.User\`의 인스턴스가 된다.

그것들을 다음과 같이 :attr:~django.contrib.auth.models.User.is\_authenticated\`로 구분할 수 있다.

```
if request.user.is_authenticated:
    # Do something for authenticated users.
    ...
else:
    # Do something for anonymous users.
    ...
```

### 사용자가 로그인 하는법

현재 세션에 연결하려는 인증된 사용자가 있는 경우 - 이것은 [`login()`](#django.contrib.auth.login) 기능으로 수행된다.

#### `login(request, user, backend=None)`

사용자를 로그인하려면 보기에서 `HttpRequest()` 객체와 [`User`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User) 객체가 필요하다. :func:~django.contrib.auth.login()\`은 Django의 세션 프레임워크를 사용하여 세션에 사용자 ID를 저장한다.

익명 세션 동안 설정된 모든 데이터는 사용자가 로그인한 후에도 세션에 유지된다.

이 예는 [`authenticate()`](#django.contrib.auth.authenticate) 및 [`login()`](#django.contrib.auth.login):을 모두 사용하는 방법을 보여준다.

```
from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(request, username=username, password=password)
    if user is not None:
        login(request, user)
        # Redirect to a success page.
        ...
    else:
        # Return an 'invalid login' error message.
        ...
```

#### 인증 백엔드 선택

사용자가 로그인하면 사용자의 세션에 사용자의 ID와 인증에 사용된 백엔드가 저장된다. 이렇게 하면 동일한 :ref:authentication backend \<authentication-backends\>\`가 향후 요청에서 사용자의 세부 정보를 가져올 수 있다. 세션에 저장할 인증 백엔드는 다음과 같이 선택된다.

1. 제공되는 경우 선택적 `backend` 인수 값을 사용한다.
2. 존재하는 경우 `user.backend` 속성 값을 사용한다. 이렇게 하면 [`authenticate()`](#django.contrib.auth.authenticate), [`login()`](#django.contrib.auth.login): , ``backend`()`` 속성을 설정한다
3. 하나뿐인 경우 :setting:AUTHENTICATION\_BACKENDS\`에 backend\`\`를 사용한다
4. 그렇지 않으면 예외를 발생시킨다.

사례 1과 2의 경우 `backend` 인수 또는 `user.backend` 속성의 값은 실제 백엔드 클래스가 아니라 점으로 구분된 import 경로 문자열(예: :setting:AUTHENTICATION\_BACKENDS\`에 있음)이어야 한다.

### 사용자가 로그아웃 하는법

#### `logout(request)`

``django.contrib.auth.login()`을 통해 로그인한 사용자를 로그아웃하려면 보기 내에서 :func:`django.contrib.auth.logout()`을 사용한다. :class:`~django.http.HttpRequest()`` 객체를 사용하며 반환 값이 없다. 예시:

```
from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Redirect to a success page.
```

:func:~django.contrib.auth.logout()\`은 사용자가 로그인하지 않은 경우 오류를 발생시키지 않는다.

:func:~django.contrib.auth.logout()\`을 호출하면 현재 요청에 대한 세션 데이터가 완전히 지워진다. 모든 기존 데이터가 제거된다. 이는 다른 사람이 동일한 웹 브라우저를 사용하여 로그인하고 이전 사용자의 세션 데이터에 액세스하는 것을 방지하기 위한 것이다. 사용자가 로그아웃한 직후에 사용할 수 있는 세션에 무엇이든 넣고 싶다면 :func:django.contrib.auth.logout()\`을 호출한 *후에* 수행하십시오.

### 로그인한 사용자의 접근 제한하기

#### 기본 방법

페이지에 대한 액세스를 제한하는 기본적인 방법은 :attr:request.user.is\_authenticated \<django.contrib.auth.models.User.is\_authenticated\>\`를 확인하고 로그인 페이지로 리디렉션하는 것이다.

```
from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
    if not request.user.is_authenticated:
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    # ...
```

…또는 오류 메시지 표시한다.

```
from django.shortcuts import render

def my_view(request):
    if not request.user.is_authenticated:
        return render(request, 'myapp/login_error.html')
    # ...
```

#### `login_required` 데코레이터

#### `login_required(redirect_field_name='next', login_url=None)`

바로 가기로 편리한 [`login_required()`](#django.contrib.auth.decorators.login_required) decorator::를 사용할 수 있다.

```
from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...
```

:func:~django.contrib.auth.decorators.login\_required\`는 다음을 수행한다.

- 사용자가 로그인하지 않은 경우 쿼리 문자열에 현재 절대 경로를 전달하여 `` settings.LOGIN_URL<LOGIN_URL> `로 리디렉션한다. 예: ` ``/accounts/login/?next=/polls/3/.
- 사용자가 로그인되어 있으면 정상적으로 뷰를 실행한다. 뷰 코드는 사용자가 로그인했다고 가정할 수 있다.

기본적으로 인증 성공 시 사용자가 리디렉션되어야 하는 경로는 ```"next"``라는 쿼리 문자열 매개변수에 저장된다. 이 매개변수에 다른 이름을 사용하고 싶다면 :func:`~django.contrib.auth.decorators.login_required`는 선택적 ``redirect_field_name``` 매개변수::를 사용한다.

```
from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
    ...
```

```redirect_field_name``에 값을 제공하면 리디렉션 경로를 저장하는 템플릿 컨텍스트 변수가 ``"next"``` (기본값) 이 아닌 `redirect_field_name` 값을 키로 사용하기 때문에 로그인 템플릿도 커스터마이즈해야 할 가능성이 크다.

```login_required`는 선택적 ``login_url`()``` 매개변수도 사용한다. 예시:

```
from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...
```

`login_url` 매개변수를 지정하지 않으면 :setting:settings.LOGIN\_URL \<LOGIN\_URL\>\`과 로그인 보기가 제대로 연결되어 있는지 확인해야 합니다. 예를 들어 기본값을 사용하여 URLconf에 다음 줄을 추가한다.

```
from django.contrib.auth import views as auth_views

path('accounts/login/', auth_views.LoginView.as_view()),
```

:setting:settings.LOGIN\_URL \<LOGIN\_URL\>\`은 뷰 함수 이름과 :ref:named URL patterns \<naming-url-patterns\>\`도 허용한다. 이렇게 하면 설정을 업데이트하지 않고도 URLconf 내에서 로그인 뷰를 자유롭게 다시 매핑할 수 있다.

> **Note**
>
> `login_required` decorator는 사용자의 `is_active` 플래그를 확인하지 않지만 기본 :setting:AUTHENTICATION\_BACKENDS\`는 비활성 사용자를 거부한다.

> **See also**
>
> Django의 관리자를 위한 커스텀 뷰를 작성하는 경우(또는 내장된 뷰에서 사용하는 것과 동일한 권한 부여 확인이 필요한 경우) [`django.contrib.admin.views.decorators.staff_member_required()`](/ko/4.0/ref/contrib/admin/#django.contrib.admin.views.decorators.staff_member_required) decorator가 login\_required()\`\`의 유용한 대안임을 찾을 수 있다.

#### `LoginRequired` 믹스인

:doc:class-based views \</topics/class-based-views/index\>\`를 사용할 때 LoginRequiredMixin\`\`을 사용하여 login\_required\`\`와 동일한 동작을 얻을 수 있다. 이 믹스인은 상속 목록에서 가장 왼쪽에 있어야 한다.

#### `class LoginRequiredMixin`

뷰가 이 믹스인을 사용하는 경우 인증되지 않은 사용자의 모든 요청은 로그인 페이지로 리디렉션되거나 [`raise_exception`](#django.contrib.auth.mixins.AccessMixin.raise_exception) 매개변수에 따라 HTTP 403 Forbidden 오류가 표시된다.

:class:~django.contrib.auth.mixins.AccessMixin\`의 매개변수를 설정하여 권한이 없는 사용자 처리를 커스터마이즈할 수 있다.

```
from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'
```

> **Note**
>
> `login_required` 데코레이터와 마찬가지로 이 믹스인은 사용자의 `is_active` 플래그를 확인하지 않지만 기본 :setting:AUTHENTICATION\_BACKENDS\`는 비활성 사용자를 거부한다.

#### 테스트를 통과한 로그인 사용자에 대한 액세스 제한

특정 권한이나 다른 테스트를 기반으로 액세스를 제한하려면 기본적으로 이전 섹션에서 설명한 것과 동일한 작업을 수행한다.

뷰에서 직접 :attr:request.user \<django.http.HttpRequest.user\>\`에 대한 테스트를 실행할 수 있다. 예를 들어, 이 뷰는 사용자가 원하는 도메인에 이메일이 있는지 확인하고 그렇지 않은 경우 로그인 페이지로 리디렉션한다.

```
from django.shortcuts import redirect

def my_view(request):
    if not request.user.email.endswith('@example.com'):
        return redirect('/login/?next=%s' % request.path)
    # ...
```

#### `user_passes_test(test_func, login_url=None, redirect_field_name='next')`

단축키로 콜러블이 ```False``를 반환할 때 리디렉션을 수행하는 편리한 ``user_passes_test``` decorator를 사용할 수 있다.

```
from django.contrib.auth.decorators import user_passes_test

def email_check(user):
    return user.email.endswith('@example.com')

@user_passes_test(email_check)
def my_view(request):
    ...
```

`User()` 객체를 취하고 사용자가 페이지를 볼 수 있는 경우 True\`\`를 반환하는 콜러블. :func:~django.contrib.auth.decorators.user\_passes\_test\`는 자동으로 :class:~django.contrib.auth.models.User\`가 익명이 아닌지 확인하지 않는다는 점에 유의해야 한다.

:func:~django.contrib.auth.decorators.user\_passes\_test\`는 두 개의 선택적 인수를 사용한다.

**`login_url`**

  테스트를 통과하지 못한 사용자가 리디렉션될 URL을 지정할 수 있다. 로그인 페이지일 수 있으며 지정하지 않으면 기본값은 :setting:settings.LOGIN\_URL \<LOGIN\_URL\>\`이다.

**`redirect_field_name`**

  :func:~django.contrib.auth.decorators.login\_required\`와 동일하다. None\`\`으로 설정하면 URL에서 제거된다. 테스트를 통과하지 못한 사용자를 “다음 페이지”가 없는 비로그인 페이지로 리디렉션하는 경우 이 작업을 수행할 수 있다.

예시:

```
@user_passes_test(email_check, login_url='/login/')
def my_view(request):
    ...
```

#### `class UserPassesTestMixin`

:doc:class-based views \</topics/class-based-views/index\>\`를 사용하는 경우 UserPassesTestMixin\`\`을 사용하여 이를 수행할 수 있다.

#### `test_func()`

수행되는 테스트를 제공하려면 클래스의 `test_func()` 메서드를 재정의해야 한다. 또한 :class:~django.contrib.auth.mixins.AccessMixin\`의 매개변수를 설정하여 권한이 없는 사용자 처리를 커스터마이즈할 수 있다.

```
from django.contrib.auth.mixins import UserPassesTestMixin

class MyView(UserPassesTestMixin, View):

    def test_func(self):
        return self.request.user.email.endswith('@example.com')
```

#### `get_test_func()`

또한 `get_test_func()` 메소드를 재정의하여 mixin이 검사를 위해 ([`test_func()`](#django.contrib.auth.mixins.UserPassesTestMixin.test_func) 대신) 다른 이름의 함수를 사용하도록 할 수도 있다.

> **UserPassesTestMixin 스태킹(Stacking)**
>
> UserPassesTestMixin\`\`이 구현되는 방식으로 인해 상속 목록에 쌓을 수 없다. 다음은 작동하지 않는다:
>
> ```
> class TestMixin1(UserPassesTestMixin):
>     def test_func(self):
>         return self.request.user.email.endswith('@example.com')
>
> class TestMixin2(UserPassesTestMixin):
>     def test_func(self):
>         return self.request.user.username.startswith('django')
>
> class MyView(TestMixin1, TestMixin2, View):
>     ...
> ```
>
> TestMixin1\`\`이 super()\`\`를 호출하고 해당 결과를 고려하면 TestMixin1\`\`은 더 이상 독립 실행형으로 작동하지 않는다.

#### `permission_required` decorator

#### `permission_required(perm, login_url=None, raise_exception=False)`

사용자에게 특정 권한이 있는지 여부를 확인하는 것은 상대적으로 일반적인 작업이다. 그런 이유로 Django는 이 경우에 대한 바로 가기를 제공한다. [`permission_required()`](#django.contrib.auth.decorators.permission_required) decorator:

```
from django.contrib.auth.decorators import permission_required

@permission_required('polls.add_choice')
def my_view(request):
    ...
```

[`has_perm()`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.has_perm) 메서드와 마찬가지로 권한 이름은 `"<app label>.<permission codename>"` 형식을 취한다(즉, `polls` 애플리케이션의 모델에 대한 권한의 경우 `polls.add_choice`).

decorator는 반복 가능한 권한을 가질 수도 있습니다. 이 경우 사용자는 뷰에 액세스하기 위해 모든 권한을 가지고 있어야 한다.

```permission_required()`도 선택적 ``login_url`()``` 매개변수를 사용한다.

```
from django.contrib.auth.decorators import permission_required

@permission_required('polls.add_choice', login_url='/loginpage/')
def my_view(request):
    ...
```

[`login_required()`](#django.contrib.auth.decorators.login_required) 데코레이터에서와 같이 login\_url\`\`의 기본값은 :setting:settings.LOGIN\_URL \<LOGIN\_URL\>\`이다.

`raise_exception` 매개변수가 지정되면 데코레이터는 로그인 페이지로 리디렉션하는 대신 :exc:~django.core.exceptions.PermissionDenied\`를 발생시켜 :ref:403(HTTP Forbidden) view\<http\_forbidden\_view\>’를 표시한다.

raise\_exception\`\`을 사용하고 사용자에게 먼저 로그인할 기회를 주고 싶다면 [`login_required()`](#django.contrib.auth.decorators.login_required) 데코레이터를 추가할 수 있다:

```
from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('polls.add_choice', raise_exception=True)
def my_view(request):
    ...
```

이는 또한 :class:.LoginView\`의 redirect\_authenticated\_user=True\`\`이고 로그인한 사용자에게 필요한 모든 권한이 없는 경우 리디렉션 루프를 방지한다.

#### `PermissionRequiredMixin` 믹스인

:doc:class-based views\`에 권한 검사를 적용하려면 PermissionRequiredMixin\`\`을 사용할 수 있다.

#### `class PermissionRequiredMixin`

이 믹스인은 `permission_required` decorator와 마찬가지로 뷰에 액세스하는 사용자에게 주어진 권한이 모두 있는지 여부를 확인하다. `permission_required` 매개변수를 사용하여 권한(또는 권한의 이터러블)을 지정해야 한다.

```
from django.contrib.auth.mixins import PermissionRequiredMixin

class MyView(PermissionRequiredMixin, View):
    permission_required = 'polls.add_choice'
    # Or multiple of permissions:
    permission_required = ('polls.view_choice', 'polls.change_choice')
```

:class:~django.contrib.auth.mixins.AccessMixin\`의 매개변수 중 하나를 설정하여 권한이 없는 사용자의 처리를 커스터마이즈할 수 있다.

다음 메서드를 재정의할 수도 있다.

#### `get_permission_required()`

믹스인에서 사용하는 권한 이름의 이터러블을 반환한다. 기본값은 `permission_required` 속성으로, 필요한 경우 튜플로 변환된다.

#### `has_permission()`

현재 사용자에게 데코레이팅된 뷰를 실행할 수 있는 권한이 있는지 여부를 나타내는 부울을 반환한다. 기본적으로 이것은 :meth:get\_permission\_required()\`가 반환한 권한 목록과 함께 :meth:~django.contrib.auth.models.User.has\_perms()\`를 호출한 결과를 반환한다.

### 클래스 기반 뷰에서 승인되지 않은 요청 리디렉션

:doc:class-based views \</ref/class-based-views/index\>\`에서 액세스 제한을 쉽게 처리하기 위해 AccessMixin\`\`을 사용하여 액세스가 거부될 때 보기의 동작을 구성할 수 있다. 인증된 사용자는 HTTP 403 Forbidden 응답으로 액세스가 거부된다. 익명 사용자는 :attr:~django.contrib.auth.mixins.AccessMixin.raise\_exception 속성에 따라 로그인 페이지로 리디렉션되거나 HTTP 403 Forbidden 응답이 표시된다.

#### `class AccessMixin`

#### `login_url`

:meth:get\_login\_url\`에 대한 기본 반환 값이다. 기본값은 None\`\`이며 이 경우 :meth:get\_login\_url\`은 :setting:settings.LOGIN\_URL \<LOGIN\_URL\>\`로 대체된다.

#### `permission_denied_message`

:meth:get\_permission\_denied\_message\`의 기본 반환 값이다. 기본값은 빈 문자열이다.

#### `redirect_field_name`

``get_redirect_field_name`의 기본 반환 값이다. 기본값은 `()``”next”이다.

#### `raise_exception`

이 속성이 True\`\`로 설정되면 조건이 충족되지 않을 때 [`PermissionDenied`](/ko/4.0/ref/exceptions/#django.core.exceptions.PermissionDenied) 예외가 발생한다. False\`\`(기본값)인 경우 익명 사용자는 로그인 페이지로 리디렉션된다.

#### `get_login_url()`

테스트를 통과하지 못한 사용자가 리디렉션될 URL을 반환한다. 설정되면 :attr:login\_url\`을 반환하고 그렇지 않으면 :setting:settings.LOGIN\_URL \<LOGIN\_URL\>\`을 반환한다.

#### `get_permission_denied_message()`

```raise_exception`이 ``True``인 경우 이 메서드를 사용하여 사용자에게 표시하기 위해 오류 처리기에 전달되는 오류 메시지를 제어할 수 있다. 기본적으로 :attr:`permission_denied_message``` 속성을 반환한다.

#### `get_redirect_field_name()`

로그인 성공 후 사용자가 리디렉션되어야 하는 URL을 포함할 쿼리 매개변수의 이름을 반환한다. 이것을 None\`\`으로 설정하면 쿼리 매개변수가 추가되지 않는다. 기본적으로 [`redirect_field_name`](#django.contrib.auth.mixins.AccessMixin.redirect_field_name) 속성을 반환한다.

#### `handle_no_permission()`

`raise_exception` 값에 따라, 이 메소드는 [`PermissionDenied`](/ko/4.0/ref/exceptions/#django.core.exceptions.PermissionDenied) 예외를 발생시키거나 사용자를 login\_url\`\`로 리디렉션하며, 설정되어 있는 경우 선택적으로 redirect\_field\_name\`\`을 포함한다.

#### 패스워드 변경시 세션 무효화

``AUTH_USER_MODEL`이 :class:`~django.contrib.auth.models.AbstractBaseUser`에서 상속하거나 자체 :meth:`~django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash()`` 메서드를 구현하는 경우, 인증된 세션에는 이 함수에서 반환된 해시가 포함된다. :class:~django.contrib.auth.models.AbstractBaseUser\`의 경우 비밀번호 필드의 HMAC이다. Django는 각 요청에 대한 세션의 해시가 요청 중에 계산된 해시와 일치하는지 확인한다. 이를 통해 사용자는 암호를 변경하여 모든 세션에서 로그아웃할 수 있다.

Django, [`PasswordChangeView`](#django.contrib.auth.views.PasswordChangeView) 에 포함된 기본 비밀번호 변경 보기 및 [`django.contrib.auth`](/ko/4.0/topics/auth/#module-django.contrib.auth) 관리자의 `user_change_password` 보기는 새 비밀번호 해시로 세션을 업데이트하여 자신의 비밀번호를 변경한 사용자는 로그아웃되지 않는다. 사용자 정의 비밀번호 변경 보기가 있고 유사한 동작을 원하면 [`update_session_auth_hash()`](#django.contrib.auth.update_session_auth_hash) 기능을 사용하시오.

#### `update_session_auth_hash(request, user)`

이 함수는 현재 요청과 새 세션 해시가 파생될 업데이트된 사용자 객체를 가져오고 세션 해시를 적절하게 업데이트한다. 또한 도난당한 세션 쿠키가 무효화되도록 세션 키를 교체한다.

예시 용례:

```
from django.contrib.auth import update_session_auth_hash

def password_change(request):
    if request.method == 'POST':
        form = PasswordChangeForm(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.user)
    else:
        ...
```

> **Note**
>
> :meth:~django.contrib.auth.models.AbstractBaseUser.get\_session\_auth\_hash()\`는 :setting:SECRET\_KEY\`를 기반으로 하므로, 새 비밀을 사용하도록 사이트를 업데이트하면 기존 세션이 모두 무효화된다.

### 인증 뷰

Django provides several views that you can use for handling login, logout, and
password management. These make use of the [stock auth forms](#built-in-auth-forms) but you can pass in your own forms as well.

Django provides no default template for the authentication views. You should
create your own templates for the views you want to use. The template context
is documented in each view, see [All authentication views](#all-authentication-views).

#### Using the views

There are different methods to implement these views in your project. The
easiest way is to include the provided URLconf in `django.contrib.auth.urls`
in your own URLconf, for example:

```
urlpatterns = [
    path('accounts/', include('django.contrib.auth.urls')),
]
```

This will include the following URL patterns:

```
accounts/login/ [name='login']
accounts/logout/ [name='logout']
accounts/password_change/ [name='password_change']
accounts/password_change/done/ [name='password_change_done']
accounts/password_reset/ [name='password_reset']
accounts/password_reset/done/ [name='password_reset_done']
accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/reset/done/ [name='password_reset_complete']
```

The views provide a URL name for easier reference. See [the URL
documentation](/ko/4.0/topics/http/urls/) for details on using named URL patterns.

If you want more control over your URLs, you can reference a specific view in
your URLconf:

```
from django.contrib.auth import views as auth_views

urlpatterns = [
    path('change-password/', auth_views.PasswordChangeView.as_view()),
]
```

The views have optional arguments you can use to alter the behavior of the
view. For example, if you want to change the template name a view uses, you can
provide the `template_name` argument. A way to do this is to provide keyword
arguments in the URLconf, these will be passed on to the view. For example:

```
urlpatterns = [
    path(
        'change-password/',
        auth_views.PasswordChangeView.as_view(template_name='change-password.html'),
    ),
]
```

All views are [class-based](/ko/4.0/topics/class-based-views/), which allows
you to easily customize them by subclassing.

#### All authentication views

This is a list with all the views `django.contrib.auth` provides. For
implementation details see [Using the views](#using-the-views).

#### `class LoginView`

**URL name:** `login`

See [the URL documentation](/ko/4.0/topics/http/urls/) for details on using
named URL patterns.

**Methods and Attributes**

#### `template_name`

The name of a template to display for the view used to log the user in.
Defaults to `registration/login.html`.

#### `next_page`

> **New in Django 4.0**

The URL to redirect to after login. Defaults to
[`LOGIN_REDIRECT_URL`](/ko/4.0/ref/settings/#std-setting-LOGIN_REDIRECT_URL).

#### `redirect_field_name`

The name of a `GET` field containing the URL to redirect to after
login. Defaults to `next`. Overrides the
[`get_default_redirect_url()`](#django.contrib.auth.views.LoginView.get_default_redirect_url) URL if the given `GET` parameter is
passed.

#### `authentication_form`

A callable (typically a form class) to use for authentication. Defaults
to [`AuthenticationForm`](#django.contrib.auth.forms.AuthenticationForm).

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

#### `redirect_authenticated_user`

A boolean that controls whether or not authenticated users accessing
the login page will be redirected as if they had just successfully
logged in. Defaults to `False`.

> **Warning**
>
> If you enable `redirect_authenticated_user`, other websites will
> be able to determine if their visitors are authenticated on your
> site by requesting redirect URLs to image files on your website. To
> avoid this “[social media fingerprinting](https://robinlinus.github.io/socialmedia-leak/)” information
> leakage, host all images and your favicon on a separate domain.
>
> Enabling `redirect_authenticated_user` can also result in a
> redirect loop when using the [`permission_required()`](#django.contrib.auth.decorators.permission_required) decorator
> unless the `raise_exception` parameter is used.

#### `success_url_allowed_hosts`

A [`set`](https://docs.python.org/3/library/stdtypes.html#set) of hosts, in addition to [`request.get_host()`](/ko/4.0/ref/request-response/#django.http.HttpRequest.get_host), that are safe for redirecting
after login. Defaults to an empty [`set`](https://docs.python.org/3/library/stdtypes.html#set).

#### `get_default_redirect_url()`

> **New in Django 4.0**

Returns the URL to redirect to after login. The default implementation
resolves and returns [`next_page`](#django.contrib.auth.views.LoginView.next_page) if set, or
[`LOGIN_REDIRECT_URL`](/ko/4.0/ref/settings/#std-setting-LOGIN_REDIRECT_URL) otherwise.

Here’s what `LoginView` does:

- If called via `GET`, it displays a login form that POSTs to the
  same URL. More on this in a bit.
- If called via `POST` with user submitted credentials, it tries to log
  the user in. If login is successful, the view redirects to the URL
  specified in `next`. If `next` isn’t provided, it redirects to
  [`settings.LOGIN_REDIRECT_URL`](/ko/4.0/ref/settings/#std-setting-LOGIN_REDIRECT_URL) (which
  defaults to `/accounts/profile/`). If login isn’t successful, it
  redisplays the login form.

It’s your responsibility to provide the html for the login template
, called `registration/login.html` by default. This template gets passed
four template context variables:

- `form`: A [`Form`](/ko/4.0/ref/forms/api/#django.forms.Form) object representing the
  [`AuthenticationForm`](#django.contrib.auth.forms.AuthenticationForm).
- `next`: The URL to redirect to after successful login. This may
  contain a query string, too.
- `site`: The current [`Site`](/ko/4.0/ref/contrib/sites/#django.contrib.sites.models.Site),
  according to the [`SITE_ID`](/ko/4.0/ref/settings/#std-setting-SITE_ID) setting. If you don’t have the
  site framework installed, this will be set to an instance of
  [`RequestSite`](/ko/4.0/ref/contrib/sites/#django.contrib.sites.requests.RequestSite), which derives the
  site name and domain from the current
  [`HttpRequest`](/ko/4.0/ref/request-response/#django.http.HttpRequest).
- `site_name`: An alias for `site.name`. If you don’t have the site
  framework installed, this will be set to the value of
  [`request.META['SERVER_NAME']`](/ko/4.0/ref/request-response/#django.http.HttpRequest.META).
  For more on sites, see [The “sites” framework](/ko/4.0/ref/contrib/sites/).

If you’d prefer not to call the template `registration/login.html`,
you can pass the `template_name` parameter via the extra arguments to
the `as_view` method in your URLconf. For example, this URLconf line would
use `myapp/login.html` instead:

```
path('accounts/login/', auth_views.LoginView.as_view(template_name='myapp/login.html')),
```

You can also specify the name of the `GET` field which contains the URL
to redirect to after login using `redirect_field_name`. By default, the
field is called `next`.

Here’s a sample `registration/login.html` template you can use as a
starting point. It assumes you have a `base.html` template that
defines a `content` block:

```html+django
{% extends "base.html" %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

{% if next %}
    {% if user.is_authenticated %}
    <p>Your account doesn't have access to this page. To proceed,
    please login with an account that has access.</p>
    {% else %}
    <p>Please login to see this page.</p>
    {% endif %}
{% endif %}

<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login">
<input type="hidden" name="next" value="{{ next }}">
</form>

{# Assumes you set up the password_reset view in your URLconf #}
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>

{% endblock %}
```

If you have customized authentication (see [Customizing Authentication](/ko/4.0/topics/auth/customizing/)) you can use a custom authentication form by
setting the `authentication_form` attribute. This form must accept a
`request` keyword argument in its `__init__()` method and provide a
`get_user()` method which returns the authenticated user object (this
method is only ever called after successful form validation).

#### `class LogoutView`

Logs a user out.

**URL name:** `logout`

**Attributes:**

#### `next_page`

The URL to redirect to after logout. Defaults to
[`LOGOUT_REDIRECT_URL`](/ko/4.0/ref/settings/#std-setting-LOGOUT_REDIRECT_URL).

#### `template_name`

The full name of a template to display after logging the user out.
Defaults to `registration/logged_out.html`.

#### `redirect_field_name`

The name of a `GET` field containing the URL to redirect to after log
out. Defaults to `'next'`. Overrides the
[`next_page`](#django.contrib.auth.views.LogoutView.next_page) URL if the given `GET` parameter is
passed.

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

#### `success_url_allowed_hosts`

A [`set`](https://docs.python.org/3/library/stdtypes.html#set) of hosts, in addition to [`request.get_host()`](/ko/4.0/ref/request-response/#django.http.HttpRequest.get_host), that are safe for redirecting
after logout. Defaults to an empty [`set`](https://docs.python.org/3/library/stdtypes.html#set).

**Template context:**

- `title`: The string “Logged out”, localized.
- `site`: The current [`Site`](/ko/4.0/ref/contrib/sites/#django.contrib.sites.models.Site),
  according to the [`SITE_ID`](/ko/4.0/ref/settings/#std-setting-SITE_ID) setting. If you don’t have the
  site framework installed, this will be set to an instance of
  [`RequestSite`](/ko/4.0/ref/contrib/sites/#django.contrib.sites.requests.RequestSite), which derives the
  site name and domain from the current
  [`HttpRequest`](/ko/4.0/ref/request-response/#django.http.HttpRequest).
- `site_name`: An alias for `site.name`. If you don’t have the site
  framework installed, this will be set to the value of
  [`request.META['SERVER_NAME']`](/ko/4.0/ref/request-response/#django.http.HttpRequest.META).
  For more on sites, see [The “sites” framework](/ko/4.0/ref/contrib/sites/).

#### `logout_then_login(request, login_url=None)`

Logs a user out, then redirects to the login page.

**URL name:** No default URL provided

**Optional arguments:**

- `login_url`: The URL of the login page to redirect to.
  Defaults to [`settings.LOGIN_URL`](/ko/4.0/ref/settings/#std-setting-LOGIN_URL) if not supplied.

#### `class PasswordChangeView`

**URL name:** `password_change`

Allows a user to change their password.

**Attributes:**

#### `template_name`

The full name of a template to use for displaying the password change
form. Defaults to `registration/password_change_form.html` if not
supplied.

#### `success_url`

The URL to redirect to after a successful password change. Defaults to
`'password_change_done'`.

#### `form_class`

A custom “change password” form which must accept a `user` keyword
argument. The form is responsible for actually changing the user’s
password. Defaults to
[`PasswordChangeForm`](#django.contrib.auth.forms.PasswordChangeForm).

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

**Template context:**

- `form`: The password change form (see `form_class` above).

#### `class PasswordChangeDoneView`

**URL name:** `password_change_done`

The page shown after a user has changed their password.

**Attributes:**

#### `template_name`

The full name of a template to use. Defaults to
`registration/password_change_done.html` if not supplied.

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

#### `class PasswordResetView`

**URL name:** `password_reset`

Allows a user to reset their password by generating a one-time use link
that can be used to reset the password, and sending that link to the
user’s registered email address.

This view will send an email if the following conditions are met:

- The email address provided exists in the system.
- The requested user is active (`User.is_active` is `True`).
- The requested user has a usable password. Users flagged with an unusable
  password (see
  [`set_unusable_password()`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.set_unusable_password)) aren’t
  allowed to request a password reset to prevent misuse when using an
  external authentication source like LDAP.

If any of these conditions are *not* met, no email will be sent, but the
user won’t receive any error message either. This prevents information
leaking to potential attackers. If you want to provide an error message in
this case, you can subclass
[`PasswordResetForm`](#django.contrib.auth.forms.PasswordResetForm) and use the
`form_class` attribute.

> **Note**
>
> Be aware that sending an email costs extra time, hence you may be
> vulnerable to an email address enumeration timing attack due to a
> difference between the duration of a reset request for an existing
> email address and the duration of a reset request for a nonexistent
> email address. To reduce the overhead, you can use a 3rd party package
> that allows to send emails asynchronously, e.g. [django-mailer](https://pypi.org/project/django-mailer/).

**Attributes:**

#### `template_name`

The full name of a template to use for displaying the password reset
form. Defaults to `registration/password_reset_form.html` if not
supplied.

#### `form_class`

Form that will be used to get the email of the user to reset the
password for. Defaults to
[`PasswordResetForm`](#django.contrib.auth.forms.PasswordResetForm).

#### `email_template_name`

The full name of a template to use for generating the email with the
reset password link. Defaults to
`registration/password_reset_email.html` if not supplied.

#### `subject_template_name`

The full name of a template to use for the subject of the email with
the reset password link. Defaults to
`registration/password_reset_subject.txt` if not supplied.

#### `token_generator`

Instance of the class to check the one time link. This will default to
`default_token_generator`, it’s an instance of
`django.contrib.auth.tokens.PasswordResetTokenGenerator`.

#### `success_url`

The URL to redirect to after a successful password reset request.
Defaults to `'password_reset_done'`.

#### `from_email`

A valid email address. By default Django uses the
[`DEFAULT_FROM_EMAIL`](/ko/4.0/ref/settings/#std-setting-DEFAULT_FROM_EMAIL).

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

#### `html_email_template_name`

The full name of a template to use for generating a
`text/html` multipart email with the password reset link. By
default, HTML email is not sent.

#### `extra_email_context`

A dictionary of context data that will be available in the email
template. It can be used to override default template context values
listed below e.g. `domain`.

**Template context:**

- `form`: The form (see `form_class` above) for resetting the user’s
  password.

**Email template context:**

- `email`: An alias for `user.email`
- `user`: The current [`User`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User),
  according to the `email` form field. Only active users are able to
  reset their passwords (`User.is_active is True`).
- `site_name`: An alias for `site.name`. If you don’t have the site
  framework installed, this will be set to the value of
  [`request.META['SERVER_NAME']`](/ko/4.0/ref/request-response/#django.http.HttpRequest.META).
  For more on sites, see [The “sites” framework](/ko/4.0/ref/contrib/sites/).
- `domain`: An alias for `site.domain`. If you don’t have the site
  framework installed, this will be set to the value of
  `request.get_host()`.
- `protocol`: http or https
- `uid`: The user’s primary key encoded in base 64.
- `token`: Token to check that the reset link is valid.

Sample `registration/password_reset_email.html` (email body template):

```html+django
Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
```

The same template context is used for subject template. Subject must be
single line plain text string.

#### `class PasswordResetDoneView`

**URL name:** `password_reset_done`

The page shown after a user has been emailed a link to reset their
password. This view is called by default if the [`PasswordResetView`](#django.contrib.auth.views.PasswordResetView)
doesn’t have an explicit `success_url` URL set.

> **Note**
>
> If the email address provided does not exist in the system, the user is
> inactive, or has an unusable password, the user will still be
> redirected to this view but no email will be sent.

**Attributes:**

#### `template_name`

The full name of a template to use. Defaults to
`registration/password_reset_done.html` if not supplied.

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

#### `class PasswordResetConfirmView`

**URL name:** `password_reset_confirm`

Presents a form for entering a new password.

**Keyword arguments from the URL:**

- `uidb64`: The user’s id encoded in base 64.
- `token`: Token to check that the password is valid.

**Attributes:**

#### `template_name`

The full name of a template to display the confirm password view.
Default value is `registration/password_reset_confirm.html`.

#### `token_generator`

Instance of the class to check the password. This will default to
`default_token_generator`, it’s an instance of
`django.contrib.auth.tokens.PasswordResetTokenGenerator`.

#### `post_reset_login`

A boolean indicating if the user should be automatically authenticated
after a successful password reset. Defaults to `False`.

#### `post_reset_login_backend`

A dotted path to the authentication backend to use when authenticating
a user if `post_reset_login` is `True`. Required only if you have
multiple [`AUTHENTICATION_BACKENDS`](/ko/4.0/ref/settings/#std-setting-AUTHENTICATION_BACKENDS) configured. Defaults to
`None`.

#### `form_class`

Form that will be used to set the password. Defaults to
[`SetPasswordForm`](#django.contrib.auth.forms.SetPasswordForm).

#### `success_url`

URL to redirect after the password reset done. Defaults to
`'password_reset_complete'`.

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

#### `reset_url_token`

Token parameter displayed as a component of password reset URLs.
Defaults to `'set-password'`.

**Template context:**

- `form`: The form (see `form_class` above) for setting the new user’s
  password.
- `validlink`: Boolean, True if the link (combination of `uidb64` and
  `token`) is valid or unused yet.

#### `class PasswordResetCompleteView`

**URL name:** `password_reset_complete`

Presents a view which informs the user that the password has been
successfully changed.

**Attributes:**

#### `template_name`

The full name of a template to display the view. Defaults to
`registration/password_reset_complete.html`.

#### `extra_context`

A dictionary of context data that will be added to the default context
data passed to the template.

### Helper functions

#### `redirect_to_login(next, login_url=None, redirect_field_name='next')`

Redirects to the login page, and then back to another URL after a
successful login.

**Required arguments:**

- `next`: The URL to redirect to after a successful login.

**Optional arguments:**

- `login_url`: The URL of the login page to redirect to.
  Defaults to [`settings.LOGIN_URL`](/ko/4.0/ref/settings/#std-setting-LOGIN_URL) if not supplied.
- `redirect_field_name`: The name of a `GET` field containing the
  URL to redirect to after log out. Overrides `next` if the given
  `GET` parameter is passed.

### Built-in forms

If you don’t want to use the built-in views, but want the convenience of not
having to write forms for this functionality, the authentication system
provides several built-in forms located in [`django.contrib.auth.forms`](#module-django.contrib.auth.forms):

> **Note**
>
> The built-in authentication forms make certain assumptions about the user
> model that they are working with. If you’re using a [custom user model](/ko/4.0/topics/auth/customizing/#auth-custom-user), it may be necessary to define your own forms for the
> authentication system. For more information, refer to the documentation
> about [using the built-in authentication forms with custom user models](/ko/4.0/topics/auth/customizing/#custom-users-and-the-built-in-auth-forms).

#### `class AdminPasswordChangeForm`

A form used in the admin interface to change a user’s password.

Takes the `user` as the first positional argument.

#### `class AuthenticationForm`

A form for logging a user in.

Takes `request` as its first positional argument, which is stored on the
form instance for use by sub-classes.

#### `confirm_login_allowed(user)`

By default, `AuthenticationForm` rejects users whose `is_active`
flag is set to `False`. You may override this behavior with a custom
policy to determine which users can log in. Do this with a custom form
that subclasses `AuthenticationForm` and overrides the
`confirm_login_allowed()` method. This method should raise a
[`ValidationError`](/ko/4.0/ref/exceptions/#django.core.exceptions.ValidationError) if the given user may
not log in.

For example, to allow all users to log in regardless of “active”
status:

```
from django.contrib.auth.forms import AuthenticationForm

class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
    def confirm_login_allowed(self, user):
        pass
```

(In this case, you’ll also need to use an authentication backend that
allows inactive users, such as
[`AllowAllUsersModelBackend`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.backends.AllowAllUsersModelBackend).)

Or to allow only some active users to log in:

```
class PickyAuthenticationForm(AuthenticationForm):
    def confirm_login_allowed(self, user):
        if not user.is_active:
            raise ValidationError(
                _("This account is inactive."),
                code='inactive',
            )
        if user.username.startswith('b'):
            raise ValidationError(
                _("Sorry, accounts starting with 'b' aren't welcome here."),
                code='no_b_users',
            )
```

#### `class PasswordChangeForm`

A form for allowing a user to change their password.

#### `class PasswordResetForm`

A form for generating and emailing a one-time use link to reset a
user’s password.

#### `send_mail(subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None)`

Uses the arguments to send an `EmailMultiAlternatives`.
Can be overridden to customize how the email is sent to the user.

**매개변수:** - `subject_template_name` – the template for the subject.
- `email_template_name` – the template for the email body.
- `context` – context passed to the `subject_template`,
  `email_template`, and `html_email_template` (if it is not
  `None`).
- `from_email` – the sender’s email.
- `to_email` – the email of the requester.
- `html_email_template_name` – the template for the HTML body;
  defaults to `None`, in which case a plain text email is sent.

By default, `save()` populates the `context` with the
same variables that
[`PasswordResetView`](#django.contrib.auth.views.PasswordResetView) passes to its
email context.

#### `class SetPasswordForm`

A form that lets a user change their password without entering the old
password.

#### `class UserChangeForm`

A form used in the admin interface to change a user’s information and
permissions.

#### `class UserCreationForm`

A [`ModelForm`](/ko/4.0/topics/forms/modelforms/#django.forms.ModelForm) for creating a new user.

It has three fields: `username` (from the user model), `password1`,
and `password2`. It verifies that `password1` and `password2` match,
validates the password using
[`validate_password()`](/ko/4.0/topics/auth/passwords/#django.contrib.auth.password_validation.validate_password), and
sets the user’s password using
[`set_password()`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.set_password).

### Authentication data in templates

The currently logged-in user and their permissions are made available in the
[template context](/ko/4.0/ref/templates/api/) when you use
[`RequestContext`](/ko/4.0/ref/templates/api/#django.template.RequestContext).

> **Technicality**
>
> Technically, these variables are only made available in the template
> context if you use [`RequestContext`](/ko/4.0/ref/templates/api/#django.template.RequestContext) and the
> `'django.contrib.auth.context_processors.auth'` context processor is
> enabled. It is in the default generated settings file. For more, see the
> [RequestContext docs](/ko/4.0/ref/templates/api/#subclassing-context-requestcontext).

#### 사용자

When rendering a template [`RequestContext`](/ko/4.0/ref/templates/api/#django.template.RequestContext), the
currently logged-in user, either a  [`User`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User)
instance or an [`AnonymousUser`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser) instance, is
stored in the template variable `{{ user }}`:

```html+django
{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
    <p>Welcome, new user. Please log in.</p>
{% endif %}
```

This template context variable is not available if a `RequestContext` is not
being used.

#### 권한

The currently logged-in user’s permissions are stored in the template variable
`{{ perms }}`. This is an instance of
`django.contrib.auth.context_processors.PermWrapper`, which is a
template-friendly proxy of permissions.

Evaluating a single-attribute lookup of `{{ perms }}` as a boolean is a proxy
to [`User.has_module_perms()`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.has_module_perms). For example, to check if
the logged-in user has any permissions in the `foo` app:

```
{% if perms.foo %}
```

Evaluating a two-level-attribute lookup as a boolean is a proxy to
[`User.has_perm()`](/ko/4.0/ref/contrib/auth/#django.contrib.auth.models.User.has_perm). For example,
to check if the logged-in user has the permission `foo.add_vote`:

```
{% if perms.foo.add_vote %}
```

Here’s a more complete example of checking permissions in a template:

```html+django
{% if perms.foo %}
    <p>You have permission to do something in the foo app.</p>
    {% if perms.foo.add_vote %}
        <p>You can vote!</p>
    {% endif %}
    {% if perms.foo.add_driving %}
        <p>You can drive!</p>
    {% endif %}
{% else %}
    <p>You don't have permission to do anything in the foo app.</p>
{% endif %}
```

It is possible to also look permissions up by `{% if in %}` statements.
For example:

```html+django
{% if 'foo' in perms %}
    {% if 'foo.add_vote' in perms %}
        <p>In lookup works, too.</p>
    {% endif %}
{% endif %}
```

## Managing users in the admin

When you have both `django.contrib.admin` and `django.contrib.auth`
installed, the admin provides a convenient way to view and manage users,
groups, and permissions. Users can be created and deleted like any Django
model. Groups can be created, and permissions can be assigned to users or
groups. A log of user edits to models made within the admin is also stored and
displayed.

### 사용자 생성하기

You should see a link to “Users” in the “Auth”
section of the main admin index page. The “Add user” admin page is different
than standard admin pages in that it requires you to choose a username and
password before allowing you to edit the rest of the user’s fields.

Also note: if you want a user account to be able to create users using the
Django admin site, you’ll need to give them permission to add users *and*
change users (i.e., the “Add user” and “Change user” permissions). If an
account has permission to add users but not to change them, that account won’t
be able to add users. Why? Because if you have permission to add users, you
have the power to create superusers, which can then, in turn, change other
users. So Django requires add *and* change permissions as a slight security
measure.

Be thoughtful about how you allow users to manage permissions. If you give a
non-superuser the ability to edit users, this is ultimately the same as giving
them superuser status because they will be able to elevate permissions of
users including themselves!

### 패스워드 변경하기

User passwords are not displayed in the admin (nor stored in the database), but
the [password storage details](/ko/4.0/topics/auth/passwords/) are displayed.
Included in the display of this information is a link to
a password change form that allows admins to change user passwords.
