Improve captcha (#7138)
This commit is contained in:
16
src/@types/recaptcha-promise.d.ts
vendored
16
src/@types/recaptcha-promise.d.ts
vendored
@ -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
56
src/misc/captcha.ts
Normal 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;
|
||||
}
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user