djangorestframework-jwtでユーザー認証とトークン認証を簡単で実現する

中国の開発者です。東京浜松町で１年ぐらい働いたことがありました。どうぞよろしくお願いします。

# djangorestframework-jwtの紹介

djangorestframework-jwtはDjangoのパッケージとして、ユーザー認証とトークン認証が簡単で実現できます。

この記事はdjangorestframework-jwtを使ってAPIの作る方法を伝えます。

**環境**
OS：Win10 or CentOS
Python：3.7
Django：3.1.2

# インストール

この二つのライリブラリが必要です。

```bash
$ pip install djangorestframework

$ pip install djangorestframework-jwt
```

# コーティング

①これらのコードをsettings.pyに改修、或は追加する

```python:settings.py
import datetime

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',  # <-- 追加する
    'my_app'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',  <-- コメントする
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# 認証用のフレームワーク
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated'
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication'
    )
}

JWT_AUTH = {
    # トークンの有効時間を設定する
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=60 * 60 * 2)
}
```

②urls.pyにコードを挿入する

ここには２つのAPIがあります。

1. userLoginはユーザー登録認証用APIです。フロントエンドはPOSTでユーザー名とパスワードをバックエンドに送って、登録してから、トークンを取得するAPIです。（ユーザーとパスワードはdjango adminのスーパーユーザーを使っていいです。）

2. getInfoはユーザー登録後、トークンを使って情報を取得するAPIです。

```python:urls.py
from django.urls import path
from my_app import views

urlpatterns = [
    path('userLogin/', views.user_login),
    path('getInfo/', views.get_info)
]
```

③views.pyにコードを挿入する

```python:views.py
import json
from django.http import JsonResponse
from django.contrib.auth import authenticate, login
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.settings import api_settings


def user_login(request):
    obj = json.loads(request.body)
    username = obj.get('username', None)
    password = obj.get('password', None)

    if username is None or password is None:
        return JsonResponse({'code': 500, 'message': '请求参数错误'})

    is_login = authenticate(request, username=username, password=password)
    if is_login is None:
        return JsonResponse({'code': 500, 'message': '账号或密码错误'})

    login(request, is_login)

    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    payload = jwt_payload_handler(is_login)
    token = jwt_encode_handler(payload)

    return JsonResponse(
        {
            'code': 200,
            'message': '登録成功',
            'data': {'token': token}
        }
    )


# APIにトークン認証を付与する
@api_view(['GET'])
@permission_classes((IsAuthenticated,))
@authentication_classes((JSONWebTokenAuthentication,))
def get_info(request):
    data = 'some info'

    return JsonResponse(
        {
            'code': 200,
            'message': 'success',
            'data': data
        }
    )
```

# フロントエンドはAPIをどう使用する

まず、POSTでuserLoginを使用して、トークンを取得する。

次、GetでgetInfoを使用して、HeadersのAuthorizationパラメータにJWT + 先ほど取得したトークンを指定してリクエストする。

```js:フロントエンドの例
token = 'abcdefg123456789'

authorization = 'JWT' + token
```

こうすると、getInfoはリクエストできます。