SQLインジェクションからデータベースを保護するために、プリペアドステートメントを使用しようとしているかなり複雑なクエリがあります。私は基本的に、単一の開始-終了ブロックの下で複数のクエリを連鎖させました。
この複合クエリは、最初にユーザーセッションが存在するかどうかを確認し、次にユーザーが禁止されているかどうかを確認し、次にユーザーが入力したタグが有効かどうかを確認し、最後に投稿をデータベースに挿入します。
クエリは次のとおりです。
query = "DO
$$
BEGIN
IF
(select exists(select user_id from sessions where unqid = $1 and user_id = $2))
THEN
IF
(select banned_till from users where unqid = $2) > now()
THEN
RAISE EXCEPTION 'User has been banned!';
ELSE
IF (
Select ( SELECT array_agg(DISTINCT name) FROM allowed_tags) @> $3)
THEN
insert into posts (unqid, title, link, content, user_id, user_nick, user_flair,
tags, tags_details, likes, likes_details)
SELECT $4, $5, $6, $7,
$2, user_nick, user_flair,
$8, $9, 1, $10
from users where unqid = $2;
ELSE
RAISE EXCEPTION 'Fake tags detected!';
END IF;
END IF;
ELSE
RAISE EXCEPTION 'User is not logged in';
END IF;
END
$$;"
DB.exec query,
session_id, session_user, tags_list, unqid, title, link, content,
tags_obj.to_json, tags_details_obj.to_json, likes_obj.to_json
このクエリは、文字列補間を使用している場合は正常に機能します。しかし、プリペアドステートメントを使おうとすると、次のようになりました。
bind message supplies 10 parameters, but prepared statement "" requires 0
クエリでプリペアドステートメントを使用するにはどうすればよいですか?
DO
ステートメントをプリペアドステートメントとして使用することはできません。
次の2つのステートメントを使用することをお勧めします。
1つは、エラー状態があるかどうかを判断するために必要な3つの結果を取得します
INSERT
ステートメントを実行するための1つ
これらの2つ目は、定期的に準備されたステートメントです。
BEGIN ... END
PL / pgSQLでトランザクションとブロックを混同しているように思われます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加