From 3feca4d25c793453a76b59e9fc1a16a41fd3a29c Mon Sep 17 00:00:00 2001 From: "nik.n" Date: Mon, 29 Jan 2024 16:50:31 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=9F=E3=83=89=E3=83=AB=E3=82=A6=E3=82=A7?= =?UTF-8?q?=E3=82=A2=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ecs/jskult-webapp/src/controller/bio_api.py | 18 ------- ecs/jskult-webapp/src/controller/login.py | 18 ------- ecs/jskult-webapp/src/controller/logout.py | 9 ---- ecs/jskult-webapp/src/main.py | 5 ++ ecs/jskult-webapp/src/middleware/__init__.py | 0 .../src/middleware/middleware.py | 47 +++++++++++++++++++ .../src/router/session_router.py | 9 ---- 7 files changed, 52 insertions(+), 54 deletions(-) create mode 100644 ecs/jskult-webapp/src/middleware/__init__.py create mode 100644 ecs/jskult-webapp/src/middleware/middleware.py diff --git a/ecs/jskult-webapp/src/controller/bio_api.py b/ecs/jskult-webapp/src/controller/bio_api.py index bbb06b69..4989a50d 100644 --- a/ecs/jskult-webapp/src/controller/bio_api.py +++ b/ecs/jskult-webapp/src/controller/bio_api.py @@ -80,15 +80,6 @@ def search_bio_data( 'count': bio_sales_lot_count }) - # X-Frame-Optionsヘッダー追加 - json_response.headers['X-Frame-Options'] = 'DENY' - # X-Content-Type-Optionsヘッダー追加 - json_response.headers['X-Content-Type-Options'] = 'nosniff' - # Strict-Transport-Securityヘッダー追加 - json_response.headers['Strict-Transport-Security'] = 'max-age=31536000 includeSubDomains' - # Cache-Controlヘッダー追加 - json_response.headers['Cache-Control'] = 'private' - # クッキーも書き換え json_response.set_cookie( key='session', @@ -162,15 +153,6 @@ async def download_bio_data( 'status': 'ok', 'download_url': download_file_url }) - - # X-Frame-Optionsヘッダー追加 - json_response.headers['X-Frame-Options'] = 'DENY' - # X-Content-Type-Optionsヘッダー追加 - json_response.headers['X-Content-Type-Options'] = 'nosniff' - # Strict-Transport-Securityヘッダー追加 - json_response.headers['Strict-Transport-Security'] = 'max-age=31536000 includeSubDomains' - # Cache-Controlヘッダー追加 - json_response.headers['Cache-Control'] = 'private' json_response.set_cookie( key='session', diff --git a/ecs/jskult-webapp/src/controller/login.py b/ecs/jskult-webapp/src/controller/login.py index bcc48fe1..5c8d904e 100644 --- a/ecs/jskult-webapp/src/controller/login.py +++ b/ecs/jskult-webapp/src/controller/login.py @@ -114,15 +114,6 @@ def login( headers={'session_key': session_key} ) - # X-Frame-Optionsヘッダー追加 - response.headers['X-Frame-Options'] = 'DENY' - # X-Content-Type-Optionsヘッダー追加 - response.headers['X-Content-Type-Options'] = 'nosniff' - # Strict-Transport-Securityヘッダー追加 - response.headers['Strict-Transport-Security'] = 'max-age=31536000 includeSubDomains' - # Cache-Controlヘッダー追加 - response.headers['Cache-Control'] = 'private' - return response @@ -180,14 +171,5 @@ def sso_authorize( status_code=status.HTTP_303_SEE_OTHER, headers={'session_key': session_key} ) - - # X-Frame-Optionsヘッダー追加 - response.headers['X-Frame-Options'] = 'DENY' - # X-Content-Type-Optionsヘッダー追加 - response.headers['X-Content-Type-Options'] = 'nosniff' - # Strict-Transport-Securityヘッダー追加 - response.headers['Strict-Transport-Security'] = 'max-age=31536000 includeSubDomains' - # Cache-Controlヘッダー追加 - response.headers['Cache-Control'] = 'private' return response diff --git a/ecs/jskult-webapp/src/controller/logout.py b/ecs/jskult-webapp/src/controller/logout.py index 99ee8813..76d9ef60 100644 --- a/ecs/jskult-webapp/src/controller/logout.py +++ b/ecs/jskult-webapp/src/controller/logout.py @@ -54,13 +54,4 @@ def logout_view( if session: session_service.delete_session(session) - # X-Frame-Optionsヘッダー追加 - template_response.headers['X-Frame-Options'] = 'DENY' - # X-Content-Type-Optionsヘッダー追加 - template_response.headers['X-Content-Type-Options'] = 'nosniff' - # Strict-Transport-Securityヘッダー追加 - template_response.headers['Strict-Transport-Security'] = 'max-age=31536000 includeSubDomains' - # Cache-Controlヘッダー追加 - template_response.headers['Cache-Control'] = 'private' - return template_response diff --git a/ecs/jskult-webapp/src/main.py b/ecs/jskult-webapp/src/main.py index 9a19d97b..61a8170f 100644 --- a/ecs/jskult-webapp/src/main.py +++ b/ecs/jskult-webapp/src/main.py @@ -10,6 +10,7 @@ from src.controller import (bio, bio_api, healthcheck, login, logout, from src.core import task from src.error.exception_handler import http_exception_handler from src.error.exceptions import UnexpectedException +from src.middleware.middleware import ErrorHandlingMiddleware, SecurityHeadersMiddleware app = FastAPI(openapi_url=None) @@ -42,5 +43,9 @@ app.add_exception_handler(status.HTTP_403_FORBIDDEN, http_exception_handler) # サーバーエラーが発生した場合のハンドラー。HTTPExceptionではハンドリングできないため、個別に設定 app.add_exception_handler(UnexpectedException, http_exception_handler) +# セキュリティヘッダー設定・サーバーエラーや認証失敗はミドルウェアで処理する +app.add_middleware(ErrorHandlingMiddleware) +app.add_middleware(SecurityHeadersMiddleware) + # サーバー起動時のイベント app.add_event_handler('startup', task.create_start_app_handler()) diff --git a/ecs/jskult-webapp/src/middleware/__init__.py b/ecs/jskult-webapp/src/middleware/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/jskult-webapp/src/middleware/middleware.py b/ecs/jskult-webapp/src/middleware/middleware.py new file mode 100644 index 00000000..64ffeb0b --- /dev/null +++ b/ecs/jskult-webapp/src/middleware/middleware.py @@ -0,0 +1,47 @@ +from fastapi import Request, Response, status +from fastapi.responses import JSONResponse +from starlette.middleware.base import BaseHTTPMiddleware + +class SecurityHeadersMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request, call_next): + response = await call_next(request) + # X-Frame-Optionsヘッダー追加 + response.headers['X-Frame-Options'] = 'DENY' + # X-Content-Type-Optionsヘッダー追加 + response.headers['X-Content-Type-Options'] = 'nosniff' + # Strict-Transport-Securityヘッダー追加 + response.headers['Strict-Transport-Security'] = 'max-age=31536000 includeSubDomains' + # Cache-Controlヘッダー追加 + response.headers['Cache-Control'] = 'private' + return response + +class ErrorHandlingMiddleware(BaseHTTPMiddleware): + # エラーハンドリングをするミドルウェア + # API内で発生したエラーをキャッチして処理を施す + + async def dispatch(self, request: Request, call_next) -> Response: + try: + response: Response = await call_next(request) + except TypeError as e: + response = JSONResponse( + {"msg": "TypeError:内容を確認してもう一度データ挿入をしてください。"}, + status.HTTP_404_NOT_FOUND, + ) + except TimeoutError as e: + response = JSONResponse( + {"msg": "TimeoutError:タイムアウトエラーが発生しました。"}, + status.HTTP_408_REQUEST_TIMEOUT, + ) + except RuntimeError as e: + response = JSONResponse( + {"msg": "RuntimeError:ランタイムエラーが発生しました。"}, + status.HTTP_500_INTERNAL_SERVER_ERROR, + ) + except Exception as e: + response = JSONResponse( + {"msg": "Exception:基底クラスエラーが発生しました。"}, + status.HTTP_500_INTERNAL_SERVER_ERROR, + ) + return response + + diff --git a/ecs/jskult-webapp/src/router/session_router.py b/ecs/jskult-webapp/src/router/session_router.py index 9672d23b..30690590 100644 --- a/ecs/jskult-webapp/src/router/session_router.py +++ b/ecs/jskult-webapp/src/router/session_router.py @@ -104,15 +104,6 @@ class AfterSetCookieSessionRoute(MeDaCaRoute): async def post_process_route(self, request: Request, response: Response): response = await super().post_process_route(request, response) - # X-Frame-Optionsヘッダー追加 - response.headers['X-Frame-Options'] = 'DENY' - # X-Content-Type-Optionsヘッダー追加 - response.headers['X-Content-Type-Options'] = 'nosniff' - # Strict-Transport-Securityヘッダー追加 - response.headers['Strict-Transport-Security'] = 'max-age=31536000 includeSubDomains' - # Cache-Controlヘッダー追加 - response.headers['Cache-Control'] = 'private' - session_key = response.headers.get('session_key', None) # セッションキーがない場合はセットせずに返す if session_key is None: