From e1b416060f438299cb2e6739378b5cb5f12de776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A6=AC?= Date: Tue, 25 Mar 2025 17:09:08 +0900 Subject: [PATCH] =?UTF-8?q?BUG916:=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E3=83=91=E3=82=B9=E3=83=AF=E3=83=BC=E3=83=89=E3=82=92?= =?UTF-8?q?=E3=83=AD=E3=82=B0=E3=81=AB=E5=87=BA=E3=81=95=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/core/operation.py | 74 +++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/backend/app/core/operation.py b/backend/app/core/operation.py index 739b165..36eab3a 100644 --- a/backend/app/core/operation.py +++ b/backend/app/core/operation.py @@ -1,4 +1,5 @@ +from urllib.parse import parse_qs, urlencode from fastapi import Request from fastapi.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware @@ -33,6 +34,48 @@ class LoggingMiddleware(BaseHTTPMiddleware): await self.log_request(request, response,state) return response + + def sanitize_password(self,data): + """ + データ内の password パラメータをフィルタリングする機能。 + dict、JSON 文字列、URL エンコード文字列、QueryDict をサポート。 + """ + if data is None: + return data + elif isinstance(data, dict): + data.pop('password', None) + return data + elif isinstance(data, list): + return [self.sanitize_password(item) for item in data] + elif isinstance(data, (str, bytes)): + if isinstance(data, bytes): + data = data.decode('utf-8') # bytes to str + # JSON解析 + try: + parsed_json = json.loads(data) + sanitized_json = self.sanitize_password(parsed_json) + return json.dumps(sanitized_json, separators=(',', ':')) + except json.JSONDecodeError: + # URL 解析 + try: + parsed_dict = parse_qs(data) + parsed_dict.pop('password', None) + return urlencode(parsed_dict, doseq=True) + except: + parts = data.split('&') + filtered_parts = [] + for part in parts: + if '=' in part: + key, _ = part.split('=', 1) + if key == 'password': + continue + filtered_parts.append(part) + return '&'.join(filtered_parts) + # QueryDict 例えば FastAPI の request.query_params) + elif hasattr(data, 'items'): + return {k: v for k, v in data.items() if k != 'password'} + return data + async def log_request(self, request: Request, response,state): try: @@ -42,15 +85,26 @@ class LoggingMiddleware(BaseHTTPMiddleware): path_template = route.path else: path_template = request.url.path - - db_operation = OperationLog(tenantid =request.state.tenant, - clientip = request.client.host if request.client else None, - useragent =headers.get("user-agent", ""), - userid = request.state.user, - operation = request.method, - function = path_template, - parameters = str({"path": request.path_params,"query": dict(request.query_params),"body": request.state.body}), - response = f"status_code:{response.status_code }" ) + + # passwordのパラメータを除外する + safe_query = self.sanitize_password(request.query_params.items()) + + # passwordのパラメータを除外する + safe_body = self.sanitize_password(request.state.body) + + db_operation = OperationLog( + tenantid =request.state.tenant, + clientip = request.client.host if request.client else None, + useragent =headers.get("user-agent", ""), + userid = request.state.user, + operation = request.method, + function = path_template, + parameters = str({ + "path": request.path_params, + "query": safe_query, + "body": safe_body + }), + response = f"status_code:{response.status_code }" ) db = request.state.db if db: @@ -71,5 +125,3 @@ class LoggingMiddleware(BaseHTTPMiddleware): async def write_log_to_db(self, db_operation,db): db.add(db_operation) db.commit() - - \ No newline at end of file