# Authentication

## 회원 가입

* 비밀번호 제공 및 확인
  * `UserCreateionForm`추가 column 정의
  * 저장 logic에서 일치하는지 확인
* 비밀번호 암호화 저장
  * `User.objects.create_user(username, email=None, password=None)`
  * `user.set_password(password)`

## 로그인

*사용자가 로그인 한 사람이다?*

### Stateless & Connectless

* 매 요청이 독립 사건
  * `cookie`가 이걸 이어준다!

## User Object

```python
from django.contrib.auth.models import User
```

* core of the **authentication system**
* [`'superusers'`](https://docs.djangoproject.com/en/3.0/ref/contrib/auth/#django.contrib.auth.models.User.is_superuser) or admin [`'staff'`](https://docs.djangoproject.com/en/3.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

![image-20200418162725783](https://github.com/pyohamen/TIL/tree/c406d6f5d12dcc8f41be5a252583f3ed8e46c4a3/images/image-20200418162725783.png)

* `AbstractBaseUser`
* `AbstractUser`
* `User`

![image-20200414200102509](https://github.com/pyohamen/TIL/tree/c406d6f5d12dcc8f41be5a252583f3ed8e46c4a3/images/image-20200414200102509.png)

### Primary attributes of default user

* `username`
* `password`
* `email`
* `first_name`
* `last_name`

### Creating Users

```python
from django.contrib.auth.models import User
user = User.objects.create_user('chloe', 'email-address@gmail.com', 'password-goes-here')

# 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 = 'kim'
user.save()
```

### Changing Password

#### 1. Using command line

```bash
$ python manage.py changepassword haha
Changing password for user 'haha'
Password: 
Password (again):
```

#### 2. Using `set_password()`

```
In [6]: ha = User.objects.get(username='haha')                                                                  

In [7]: ha                                                                                                      
Out[7]: <User: haha>

In [8]: ha.set_password('dkgkgkgk')                                                                             
In [9]: ha.save()
```

### Authenticating Users

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

* use it to verify a set of credentials
* takes credentials as keyword arguments
  * **username** and **password** for the default cases
* returns `User` object if credentials are valid for a backend

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

장바구니

1. 사용자  ---> 장바구니 ---> 쿠팡
2. 사용자 <--- 쿠키 <--- 쿠팡
3. 장바구니 == `cookie`
4. 구매내역 == `data`

*로그인 == create*

*로그아웃 == delete*

### 로그인 Form

```python
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
```

* `AutehticationForm`은 **ModelForm** 이 아니라 그냥 **Form** 이다!

### 로그인 함수

```python
from django.contrib.auth import get_user_model, login
```

```python
def signin(request):
    if request.method == 'POST':
        # 사용자가 보낸 값 -> form
        form = AuthenticationForm(request, request.POST)
        # 검증
        # -> 검증 완료 시 로그인
        if form.is_valid():
            login(request, form.get_user())
            return redirect('accounts:index')
    else:    
        form = AuthenticationForm()
    context = {
        'form':form 
    }
    return render(request, 'accounts/signin.html', context)
```

* `else`문 처리를 매끄럽게 하기 위해 첫번째 `if`로 **POST**를 먼저 거른다
  * why?&#x20;
    * 만약 **GET**을 먼저 거르면, **POST**에서 `.is_valid()`에 걸리지 않고 `else` 로 떨어지면 다시 render하는 코드 써줘야해서!
    * 즉, *code의 경제성을 위해 \*POST* 를 먼저 쓴다!

`+`

#### `POST` 로 먼저 분기하는 이유

1. 코드의 간결성
2. REST API 대응
   * 현재 우리는 GET & POST만 대응하고 있는데 이후에 RESTful 하게 메소드 구성할 경우 GET/POST/PUT/DELETE 여러개의 메소드가 오게 되고 GET method가 마지막에에 핸들링되는 형태가 가장 간결한 코드 구성이 가능!

## Message Framework

**new**

-> 글 작성 페이지 (form)

**create**

-> DB에저장

-> render

-> redirect(성공여부)

-> redirect('articles:index')

*HTTP는 request와 response의 반복이다!*

#### HTTP

* stateless (무 상태성)
  * 한번 요청을 보내면 상태(과거)를 알 수 없음
  * 모든 요청 & 응답은 일회성이다
  * HTTP는 단절적인 protocol
* connectionless (무 연결성)

### Message Framework

* 이전의 상태를 다음 `Request` & `Response`에 넘겨준다는 것이 의미가 있다
  * Fallback Storage
    * Cookie 가 안되면 Session

## Dynamic view

Article CRUD

* title, content, create\_at, updated\_at

User CRUD (직접 < Django)

`+`

* in memory cache -> ram에 띄워놓는 cache라고 생각하면 됨
  * memcached
  * redis
* 구글 광고 아이디......gdpr
* macaddress = 기기정보


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pyohamen.gitbook.io/til/django/07_authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
