ブルートフォースログインを防ぐために(最善を尽くして)このトリガーがあります。次の2つの機能があります。
失敗したログインが過去3分間に同じIPアドレスから4回を超えて(つまり、正確に5回読んだ場合)試行された場合、そのIP_addressがblacklisted_ipsテーブルに追加されます。その場合、IPアドレスには、表の列で指定された「クールダウン」期間があります。
失敗したログインが同じユーザー名から過去2分間(IPアドレスに依存しないため)に3回以上試行された場合(正確に4回読み取った場合)、ユーザー名はblacklisted_usernamesテーブルに追加されます。ユーザー名には、表の列で指定された「クールダウン」期間があります。
私の質問は、このトリガーを見ると、パフォーマンスが非効率的に見えることです。それは正しいと思いますか、それともパフォーマンスへの影響は無視できますか?
CREATE TRIGGER prevent_brute_force
AFTER INSERT ON login_att
FOR EACH ROW
BEGIN
SELECT ip_add, was_success INTO @ip, @result
FROM login_att
ORDER BY login_att_id DESC LIMIT 1;
SELECT ip_add INTO @check_ip
FROM login_att
WHERE login_att_time > DATE_SUB(NOW(), INTERVAL 3 MINUTE)
AND ip_add = @ip
HAVING COUNT(ip_add) > 4;
IF @check_ip IS NOT NULL
THEN
IF @result = 0
THEN
INSERT INTO blacklisted_ips (ip_add) VALUES (@ip);
END IF;
END IF;
SELECT username_att into @username_att
FROM login_att
WHERE login_att_time > DATE_SUB(NOW(), INTERVAL 2 MINUTE)
AND was_success=0 HAVING COUNT(username_att) > 3;
IF @username_att IS NOT NULL
THEN
INSERT INTO blacklisted_users (username) VALUES (@username_att);
END IF;
END$$
パフォーマンスを評価する最良の方法は、それを測定することです。実際のアプリケーションで、またはさらに優れた方法として、トラフィックのコピーまたはそのエミュレーションを備えたステージング環境でそれを評価できるのはあなただけです。
ハードウェア、実行中の他のコード、スループット、これらの新しいクエリの速度、所有しているデータの量などから、知りたいことがわかります。つまり、同じコードがさまざまな状況で成功したり壊れたりする可能性があるということです。
とは言っても、システムについてあまり知らなくても、アイデアの高水準の意見が機能する場合は、通常、外部ログ(またはlogin_attテーブル)に基づいてこの種の分析を非同期で行います発生頻度が十分でない場合、通常のユーザーを罰したくない。また、トリガーは、アプリケーションロジックを処理するための私のお気に入りの方法ではありません。ただし、ソースコードを変更できない場合は、レイテンシの合計に大きな影響はありません。テストして問題がないように見えますが、何千回も並行して試行してもアプリケーションが壊れないかどうかテストしてください。余分な書き込みのため、毎秒。
それは問題ではありません。
有効なログインとは、ユーザーがシステムで行った作業全体のごく一部です。したがって、その「小さな」割合が増加しても、それはまだ「小さな」影響です。
その間、誰がハッカーで何が起こるか気にしています。
オーバーヘッドに関しては、マイナーになります。
@RickJamesは良い点だと思いますが、とにかくトリガーを少しでも最適化したい場合は、いくつか注意点があります。
IF
ステートメントは毎回完全に再解析されるため、回避することをお勧めしますが、もちろん必要な場合もあります。あなたの場合、IF
sなしでコードを機能させる方法がよくわかりません。SELECT
は不要です。 AFTER INSERT
トリガー列名に接頭辞NEW
を使用して、挿入された行の値にアクセスできるため、次のようになります。NEW.ip_add
、NEW.was_success
は、ここで必要な値を提供します。IF
ステートメント(IF @check_ip ... THEN IF @result = 0 THEN
)、あなたは単にIF @check_ip IS NOT NULL AND NEW.was_success = 0 THEN
。