#はじめに
本稿ではDjangoで構築したサーバに以下の最低限のセキュリティ対策を行う手順を解説します。(DjangoでWebアプリケーション構築済である前提とします。)
- ログイン認証の追加
- SSL対応 (記事作成中)
#ログイン用アプリケーションの作成
まずプロジェクト配下でログイン機能用のアプリケーションを作成する。
$ python manage.py startapp accounts
アプリケーション作成後のプロジェクト構成は以下。
sample_project
├── accounts <- ログイン用アプリケーション
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── sample_app <- 固有アプリケーション
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── index.html
│ ├── urls.py
│ └── views.py
├── config
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
プロジェクト配下のsetting.pyとurls.pyにログイン用アプリケーション用の設定を追記。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'sample_app.apps.SampleAppConfig', # Custom App
'accounts.apps.AccountsConfig', # 追加
]
urlpatterns = [
path('admin/', admin.site.urls),
path('sample_app/', include('sample_app.urls')), # Custom App
path('', include('accounts.urls')), # 追加 ログイン用
]
#ログイン用フォーム、ビュー、テンプレートの作成
以下、ログイン画面の部品をそれぞれ作成する。
- ログイン用フォームの定義:forms.py
- ログイン用ビューの定義:view.py
- ログイン画面用テンプレート:login.html
フォームの定義はDjango標準クラスのAuthenticationFormを用いる。
from django.contrib.auth.forms import AuthenticationForm
class LoginForm(AuthenticationForm):
"""ログインフォーム"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
field.widget.attrs['placeholder'] = field.label
importしているクラスは以下。
クラス名 | 機能 |
---|---|
LoginRequiredMixin | ログインしたユーザだけ閲覧できるようにする |
LoginView | ログイン機能 |
LogoutView | ログアウト機能 |
LogoutForm | 上記で定義したログイン用フォーム |
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import(LoginView, LogoutView)
from .forms import LoginForm
class Login(LoginView):
"""ログインページ"""
form_class = LoginForm
template_name = 'login.html'
class Logout(LoginRequiredMixin, LogoutView):
"""ログアウトページ"""
template_name = 'login.html'
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>LOGIN</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
{{ field }}
{% endfor %}
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
<button type="submit">ログイン</button>
</form>
</body>
</html>
フォーム、ビュー、テンプレート追加後のプロジェクト構成は以下。
sample_project
├── accounts <- ログイン用アプリケーション
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── login.html
│ ├── urls.py
│ └── views.py
├── sample_app <- 固有アプリケーション
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── index.html
│ ├── urls.py
│ └── views.py
├── config
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
ログイン用アプリケーションのurls.pyにURLとビューの紐づけを追記する。
urlpatterns =[
path('login/', views.Login.as_view(), name='login'),
]
#リダイレクトURLの設定
setting.pyに未ログイン時に表示されるURL、ログイン・ログアウト時のリダイレクトURLを設定する。
LOGIN_URL = '/login' # ログインしていないときのリダイレクト先
LOGIN_REDIRECT_URL = '/sample_app/index' # ログイン後のリダイレクト先
LOGOUT_REDIRECT_URL = '/login' # ログアウト後のリダイレクト先
ログイン認証を追加するアプリケーションの設定
ログイン先のアプリケーションのビューにログイン必須設定を行う。
クラスベースのビューの場合、LoginRequiredMixinをimportして継承することでログイン必須となる。
from django.contrib.auth.mixins import LoginRequiredMixin
class Test(LoginRequiredMixin, TemplateView):
template_name = 'index.html'
メソッドベースのビューの場合、@login_requiredのアノテーションを付与することでログイン必須となる。
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
@login_required
def index(request):
return render(request, 'index.html')
#ユーザーの作成
プロジェクト配下でユーザーを作成する。
$ python manage.py createsuperuser
#テスト
これでアプリケーションを起動してログインURLにアクセスするとログインフォームが表示されるはずなので、作成したユーザーのID/Passでログインできればログイン認証成功です。