Improve captcha (#7138)

This commit is contained in:
MeiMei
2021-02-06 11:46:47 +09:00
committed by GitHub
parent 41d7515f85
commit 0e45f10d99
5 changed files with 62 additions and 60 deletions

View File

@ -1,16 +0,0 @@
declare module 'recaptcha-promise' {
interface IVerifyOptions {
secret_key?: string;
}
interface IVerify {
(response: string, remoteAddress?: string): Promise<boolean>;
init(options: IVerifyOptions): IVerify;
}
namespace recaptchaPromise {} // Hack
const verify: IVerify;
export = verify;
}

56
src/misc/captcha.ts Normal file
View File

@ -0,0 +1,56 @@
import fetch from 'node-fetch';
import { URLSearchParams } from 'url';
import { getAgentByUrl } from './fetch';
import config from '../config';
export async function verifyRecaptcha(secret: string, response: string) {
const result = await getCaptchaResponse('https://www.recaptcha.net/recaptcha/api/siteverify', secret, response).catch(e => {
throw `recaptcha-request-failed: ${e}`;
});
if (result.success !== true) {
const errorCodes = result['error-codes'] ? result['error-codes']?.join(', ') : '';
throw `recaptcha-failed: ${errorCodes}`;
}
}
export async function verifyHcaptcha(secret: string, response: string) {
const result = await getCaptchaResponse('https://hcaptcha.com/siteverify', secret, response).catch(e => {
throw `hcaptcha-request-failed: ${e}`;
});
if (result.success !== true) {
const errorCodes = result['error-codes'] ? result['error-codes']?.join(', ') : '';
throw `hcaptcha-failed: ${errorCodes}`;
}
}
type CaptchaResponse = {
success: boolean;
'error-codes'?: string[];
};
async function getCaptchaResponse(url: string, secret: string, response: string): Promise<CaptchaResponse> {
const params = new URLSearchParams({
secret,
response
});
const res = await fetch(url, {
method: 'POST',
body: params,
headers: {
'User-Agent': config.userAgent
},
timeout: 10 * 1000,
agent: getAgentByUrl
}).catch(e => {
throw `${e.message || e}`;
});
if (!res.ok) {
throw `${res.status}`;
}
return await res.json() as CaptchaResponse;
}

View File

@ -1,7 +1,6 @@
import * as Koa from 'koa';
import { fetchMeta } from '../../../misc/fetch-meta';
import { verify } from 'hcaptcha';
import * as recaptcha from 'recaptcha-promise';
import { verifyHcaptcha, verifyRecaptcha } from '../../../misc/captcha';
import { Users, RegistrationTickets } from '../../../models';
import { signup } from '../common/signup';
@ -14,26 +13,15 @@ export default async (ctx: Koa.Context) => {
// ただしテスト時はこの機構は障害となるため無効にする
if (process.env.NODE_ENV !== 'test') {
if (instance.enableHcaptcha && instance.hcaptchaSecretKey) {
const success = await verify(instance.hcaptchaSecretKey, body['hcaptcha-response']).then(
({ success }) => success,
() => false,
);
if (!success) {
ctx.throw(400, 'hcaptcha-failed');
}
await verifyHcaptcha(instance.hcaptchaSecretKey, body['hcaptcha-response']).catch(e => {
ctx.throw(400, e);
});
}
if (instance.enableRecaptcha && instance.recaptchaSecretKey) {
recaptcha.init({
secret_key: instance.recaptchaSecretKey
await verifyRecaptcha(instance.recaptchaSecretKey, body['g-recaptcha-response']).catch(e => {
ctx.throw(400, e);
});
const success = await recaptcha(body['g-recaptcha-response']);
if (!success) {
ctx.throw(400, 'recaptcha-failed');
}
}
}