Browse Source

feat(auth): require captcha on login and register

Made-with: Cursor
main
npmrun 6 hours ago
parent
commit
b4a46cfcdc
  1. 28
      server/api/auth/login.post.ts
  2. 27
      server/api/auth/register.post.ts

28
server/api/auth/login.post.ts

@ -1,18 +1,30 @@
import { getRequestIP } from "h3";
import { loginUser } from "#server/service/auth";
import { toPublicAuthError } from "#server/service/auth/errors";
import { setSessionCookie } from "#server/service/auth/cookie";
type LoginBody = {
username: string;
password: string;
};
import { captchaConsume } from "#server/service/captcha/store";
import { assertLoginRegisterCaptchaFieldsPresent } from "#server/service/captcha/validate-body";
import { assertUnderRateLimit } from "#server/utils/simple-rate-limit";
export default defineWrappedResponseHandler(async (event) => {
const ip = getRequestIP(event, { xForwardedFor: true }) ?? "unknown";
assertUnderRateLimit(`auth-login:${ip}`, 30, 60_000);
const body = await readBody(event);
assertLoginRegisterCaptchaFieldsPresent(body);
if (!captchaConsume(body.captchaId, body.captchaAnswer)) {
throw createError({
statusCode: 400,
statusMessage: "验证码错误或已过期,请重试",
});
}
try {
const body = await readBody<LoginBody>(event);
const result = await loginUser(body);
const result = await loginUser({
username: body.username,
password: body.password,
});
setSessionCookie(event, result.sessionId);
return R.success({
user: result.user,
});

27
server/api/auth/register.post.ts

@ -1,12 +1,23 @@
import { getRequestIP } from "h3";
import { registerUser } from "#server/service/auth";
import { toPublicAuthError } from "#server/service/auth/errors";
type RegisterBody = {
username: string;
password: string;
};
import { captchaConsume } from "#server/service/captcha/store";
import { assertLoginRegisterCaptchaFieldsPresent } from "#server/service/captcha/validate-body";
import { assertUnderRateLimit } from "#server/utils/simple-rate-limit";
export default defineWrappedResponseHandler(async (event) => {
const ip = getRequestIP(event, { xForwardedFor: true }) ?? "unknown";
assertUnderRateLimit(`auth-register:${ip}`, 20, 60_000);
const body = await readBody(event);
assertLoginRegisterCaptchaFieldsPresent(body);
if (!captchaConsume(body.captchaId, body.captchaAnswer)) {
throw createError({
statusCode: 400,
statusMessage: "验证码错误或已过期,请重试",
});
}
const allowRegister = await event.context.config.getGlobal("allowRegister");
if (!allowRegister) {
throw createError({
@ -16,8 +27,10 @@ export default defineWrappedResponseHandler(async (event) => {
}
try {
const body = await readBody<RegisterBody>(event);
const user = await registerUser(body);
const user = await registerUser({
username: body.username,
password: body.password,
});
return R.success({
user,
});

Loading…
Cancel
Save