2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DjangoのMiddlewareでサイト攻撃を防ぐ処理を作成してみた

Last updated at Posted at 2020-04-30

以下のコマンドでDjangoプロジェクトを作成

django-admin startproject MyObj01
cd MyObj01
python manage.py startapp App

作成したファイル構成ファイルは以下の通りです。

MyObj01
├── App
│   ├── migrations
│   │   └── __init__.py
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── MyObj01
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

MyObj01\Appの下、urls.pyを新規作成

urls.py
from django.urls import path
from App import views

urlpatterns = {
    path('home', views.home, name='home'),

}

MyObj01\MyObj01中のurls.pyに以下のように追加

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app/', include(('App.urls', 'app'), namespace='app')),  # 追加
]

MyObj01\App中のviews.pyに以下のように追加

views.py
from django.http import HttpResponse


def home(request):
    return HttpResponse('Home test')

MyObj01\Appの下、MyMiddle.pyを新規作成

MyMiddle.py
import time
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
from django.core.cache import cache  # Djangoのキャッシュ機能


class AppMiddle(MiddlewareMixin):
    def process_request(self, request):
        black_ip_list = cache.get('black_ip_list', [])
        ip = request.META.get('REMOTE_ADDR')
        if ip in black_ip_list:
            return HttpResponse('使用中止')

        ip_time_list = cache.get(ip, [])
        time_temp = time.time()
        # 60秒前の更新記録を削除
        while ip_time_list and (time_temp - ip_time_list[-1]) > 60:
            ip_time_list.pop()
        ip_time_list.insert(0, time_temp)
        cache.set(ip, ip_time_list, timeout=60)
        if len(ip_time_list) > 20:
            black_ip_list.append(ip)
            # 該当IPで一週間内使用不可とする
            cache.set('black_ip_list', black_ip_list, timeout=60 * 60 * 24 * 7)
        if len(ip_time_list) > 10:
            return HttpResponse('頻繫に更新しないでください')

MyObj01\MyObj01下のsettings.pyに以下のように追加

settings.py
......

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'App',  # 追加
]

MIDDLEWARE = [
    'App.MyMiddle.AppMiddle', # 追加 (一番最初に実行するように先頭に追加)
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

......

サーバーを起動(python manage.py runserver 127.0.0.1:8000)して、
60秒内、10回以上「http://127.0.0.1:8000/app/home」更新すると「頻繫に更新しないでください」というページが表示されます、
また、60秒内、20回以上更新すると「使用中止」というページが表示されます。

2
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?