密码验证钩子
您的公司希望增强安全性,超越默认密码实现的要求,以满足安全或合规性需求。您计划跟踪密码登录尝试的状态,并在必要时通过电子邮件或登录限制采取相应措施。
由于此钩子在未经认证的请求上运行,恶意用户可能通过多次调用该钩子进行滥用。使用此钩子时需格外小心,以免无意中阻止合法用户访问您的应用程序。
在采取任何额外措施前,请验证密码是否有效以确保用户身份合法。在可能的情况下,建议发送电子邮件或通知而非直接阻止用户。
输入参数
字段 | 类型 | 描述 |
---|---|---|
user_id | string | 尝试登录用户的唯一标识符。应与 auth.users 表中的记录关联。 |
valid | boolean | 表示密码验证尝试是否有效。 |
1234{ "user_id": "3919cb6e-4215-4478-a960-6d3454326cec", "valid": true}
输出
仅在钩子成功处理输入且无错误时返回以下内容。
字段 | 类型 | 描述 |
---|---|---|
decision | string | 是否允许继续认证的决策。使用 reject 拒绝验证尝试并注销用户所有活跃会话。使用 continue 则采用 Supabase Auth 的默认行为。 |
message | string | 当决策为 reject 时显示给用户的消息。 |
should_logout_user | boolean | 当决策为 reject 时是否注销用户。对 continue 决策无效。 |
12345{ "decision": "reject", "message": "您已超过密码登录尝试的最大次数。", "should_logout_user": "false"}
作为公司内部新的安全措施,用户每10秒只能输入一次错误密码,不能超过此限制。您需要编写一个钩子来强制执行此规则。
创建表记录每个用户最后一次密码验证失败的尝试。
12345create table public.password_failed_verification_attempts ( user_id uuid not null, last_failed_at timestamp not null default now(), primary key (user_id));
创建钩子来读写该表信息。例如:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354create function public.hook_password_verification_attempt(event jsonb)returns jsonblanguage plpgsqlas $$ declare last_failed_at timestamp; begin if event->'valid' is true then -- 密码有效,接受 return jsonb_build_object('decision', 'continue'); end if; select last_failed_at into last_failed_at from public.password_failed_verification_attempts where user_id = event->'user_id'; if last_failed_at is not null and now() - last_failed_at < interval '10 seconds' then -- 上次尝试间隔过短 return jsonb_build_object( 'error', jsonb_build_object( 'http_code', 429, 'message', '请稍等片刻再重试。' ) ); end if; -- 记录本次失败尝试 insert into public.password_failed_verification_attempts ( user_id, last_failed_at ) values ( event->'user_id', now() ) on conflict do update set last_failed_at = now(); -- 最后让 Supabase Auth 执行失败尝试的默认行为 return jsonb_build_object('decision', 'continue'); end;$$;-- 分配适当权限grant all on table public.password_failed_verification_attempts to supabase_auth_admin;revoke all on table public.password_failed_verification_attempts from authenticated, anon, public;