CAPTCHA
As páginas de conta de um portal aceitam envios de qualquer pessoa: um script pode criar contas, ou fazer com que o portal redefina senhas e links de confirmação para endereços que escolher. Um CAPTCHA pede a cada visitante que comprove que é uma pessoa antes do envio do formulário. Power Portals Pro suporta Cloudflare Turnstile, Google reCAPTCHA (v2 e v3) e hCaptcha, e fica desligado até que você configure um.
Nota
O servidor verifica o desafio, não apenas a página. Uma vez configurado um provedor, os endpoints de autenticação e as páginas de conta renderizadas pelo servidor recusam o envio de um formulário protegido sem um desafio resolvido, independentemente do envio do navegador.
Quais formas são protegidas
CaptchaOptions.Forms escolhe os formulários, como uma combinação de CaptchaForms valores. O padrão protege os formulários que um chamador automático pode abusar sem saber nenhuma senha.
| CaptchaForms | Forma | Por padrão |
|---|---|---|
Register |
Criando uma conta local. | Em |
ForgotPassword |
Pedindo um link para redefinir senha. | Em |
ResendEmailConfirmation |
Pedindo outro link de confirmação por e-mail. | Em |
Login |
Fazendo login com um endereço de e-mail e senha. Ative para diminuir a tentativa de adivinhação de senha; senhas erradas repetidas também bloqueiam a conta por um tempo. | Desliga |
ExternalLogin |
Completar um login pela Microsoft, Google ou outro provedor com um endereço de e-mail que o provedor não verificou, para o qual o portal então envia uma confirmação por correio. Um login cujo endereço o provedor foi verificado é concluído sem contestação. | Desliga |
Escolhendo um provedor
Os três provedores funcionam da mesma forma no que diz respeito ao portal; eles diferem no que o visitante vê e em qual conta você precisa. Cada um tem um nível gratuito.
| Provedor | Conta que você precisa | O que o visitante vê | Links |
|---|---|---|---|
| Catraca Cloudflare | Uma conta gratuita na Cloudflare. Seu portal não precisa estar hospedado na Cloudflare nem usar seu DNS. | Geralmente não há nada para fazer: o cheque roda sozinho e só pede um clique ocasionalmente. | Painel · Documentação |
| Pesquise no Google por reCAPTCHA v2 | Uma conta do Google. | A caixa de seleção "Eu não sou um robô", às vezes seguida de um quebra-cabeça de imagem. | Console de administração · Documentação |
| hCaptcha | Uma conta hCaptcha gratuita. | Uma caixa de seleção, às vezes seguida de um quebra-cabeça de imagem. | Painel · Documentação |
| Pesquise no Google reCAPTCHA v3 | Uma conta do Google. | Nada: o Google avalia cada submissão, e o selo do Google fica no canto da página. Um visitante com pontuação baixa demais é recusado e não pode provar o contrário. | Console de administração · Documentação |
Qualquer que seja sua escolha, o provedor te dá duas chaves para o seu site: uma chave do site, que é pública e enviada para todos os navegadores para desenhar o widget, e uma chave secreta, que só o servidor usa para verificar a resposta de um visitante. Mantenha a chave secreta fora do controle de versão.
Montagem do Cloudflare Turnstile
- Cadastre-se para uma conta gratuita no dash.cloudflare.com. Você não precisa adicionar um site nem mover nenhum DNS.
- Abra o Turnstile no menu do painel e escolha Adicionar widget.
- Nomeie o widget e adicione todos os nomes de host de onde o portal é servido — seu domínio de produção, qualquer slot de implantação e
localhost, se você testar com chaves reais. - Escolha o modo Widget Gerenciado , que só pede um clique quando a Cloudflare não tem certeza.
- Crie o widget e copie sua Chave do Site e Chave Secreta.
Configurando o Google reCAPTCHA v2
- Faça login no console de administração do reCAPTCHA com uma conta do Google e crie um novo site.
- Escolha Desafio (v2) e depois a Caixa de Seleção "Eu não sou um robô".
- Adicione todos os domínios de onde o portal é servido, e
localhostse você testar com chaves reais. - Deixe o Verify the origin of reCAPTCHA ativado, para que um token resolvido em outro site seja recusado. Submeta e copie a chave do site e a chave secreta.
Importante
Use o provedor
ReCaptchaV2e aCaptcha:ReCaptchaV2seção apenas para uma chave v2 "Eu não sou um robô" — o widget mostra "Tipo de chave inválido" para qualquer outra. Uma chave v3 fica sobReCaptchaV3, abaixo; o selo invisível v2 não é suportado. O Google pode pedir para você anexar a chave a um projeto do Google Cloud; isso não muda a forma como o portal a utiliza.
Configurando o Google reCAPTCHA v3
a versão 3 não mostra desafio. A página pede ao Google um token quando o formulário é enviado, marcado com o formulário de onde veio, e o servidor recusa um token pontuado abaixo MinimumScore ou marcado para outro formulário. Use o provedor ReCaptchaV3 e sua própria seção: Captcha:ReCaptchaV3uma chave v3 é uma chave diferente da v2.
- No console de administração do reCAPTCHA, crie um novo site e escolha Baseado em Pontuação (v3).
- Adicione todos os domínios de onde o portal é servido, e
localhostse você testar com chaves reais. Deixe Verificar a origem das soluções reCAPTCHA ativada. - Submeta e copie a chave do site e a chave secreta para
Captcha:ReCaptchaV3. - Defina
MinimumScore, de 0,0 para 1,0. Ele define por padrão 0,5, o ponto de partida sugerido pelo Google; o console de administração mostra as pontuações que seus visitantes recebem, para ajustar.
Importante
Um visitante pontuado abaixo
MinimumScoreé recusado sem nada a resolver, e é orientado a tentar novamente em um instante. Aumente com cuidado e observe as pontuações no console de administração depois de fazer isso. O Google publica que não há chaves de teste para a v3.
Configuração do hCaptcha
- Inscreva-se gratuitamente em dashboard.hcaptcha.com.
- Em Sites, adicione um novo site e copie sua Chave do Site.
- Nas configurações do site, adicione todos os nomes de host de onde o portal é servido. hCaptcha não aceita
localhostou127.0.0.1: para tentar chaves reais na sua máquina, mapeie um nome comodev.example.comto127.0.0.1no arquivo do seu host e adicione isso, ou use as chaves de teste abaixo. - Copie a chave secreta das configurações da sua conta (ou do segredo próprio do site, onde o painel oferece uma).
Chaves de teste para desenvolvimento local
Cada provedor publica um par de chaves de teste que funcionam em qualquer nome de hostname, localhost incluso, e sempre passam — então você pode testar os formulários do portal antes de criar uma conta. O widget mostra que está em modo de teste.
| Provedor | Chave do local | Chave secreta |
|---|---|---|
Turnstile |
1x00000000000000000000AA |
1x0000000000000000000000000000000AA |
ReCaptchaV2 |
6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI |
6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe |
HCaptcha |
10000000-ffff-ffff-ffff-000000000001 |
0x0000000000000000000000000000000000000000 |
Importante
Chaves de teste aceitam todos os visitantes, incluindo robôs. Nunca as implante: substitua-as por suas próprias chaves antes que o portal entre em funcionamento.
Configuração do portal
Projetos gerados a partir dos templates se vinculam CaptchaOptions a partir da Captcha seção de appsettings.json, que começa com Provider set para None. Cada provedor tem uma seção própria para suas chaves — Turnstile, ReCaptchaV2, ReCaptchaV3 e HCaptcha — e Provider escolhe qual é usada, então você pode manter várias configuradas e alternar entre elas com uma única configuração. Coloque a chave do site de cada provedor em sua seção. Forms Toma os nomes do formulário separados por vírgulas; deixe de fora para manter o padrão.
{
"Captcha": {
"Provider": "Turnstile",
"Forms": "Register, ForgotPassword, ResendEmailConfirmation",
"Turnstile": {
"SiteKey": "<Turnstile site key>"
},
"ReCaptchaV2": {
"SiteKey": "<reCAPTCHA v2 site key>"
},
"ReCaptchaV3": {
"SiteKey": "<reCAPTCHA v3 site key>",
"MinimumScore": 0.5
}
}
}
Mantenha as chaves secretas nos segredos dos usuários durante o desenvolvimento, e nas configurações do Key Vault ou do App Service quando implantadas — nunca em appsettings.json. No Key Vault, nomei-as Captcha--Turnstile--SecretKey e assim por diante:
dotnet user-secrets set "Captcha:Turnstile:SecretKey" "<Turnstile secret key>"
dotnet user-secrets set "Captcha:ReCaptchaV2:SecretKey" "<reCAPTCHA v2 secret key>"
dotnet user-secrets set "Captcha:ReCaptchaV3:SecretKey" "<reCAPTCHA v3 secret key>"
dotnet user-secrets set "Captcha:HCaptcha:SecretKey" "<hCaptcha secret key>"
Esta é a linha Program.cs que lê a seção. Um portal que não foi gerado a partir de um modelo o adiciona depois AddPowerPortalsProWebServer():
builder.Services.Configure<CaptchaOptions>(builder.Configuration.GetSection("Captcha"));
Ou definir as opções no código, como qualquer outra IOptions classe:
builder.Services.Configure<CaptchaOptions>(options =>
{
options.Provider = CaptchaProvider.HCaptcha;
options.HCaptcha.SiteKey = "<site key>";
options.HCaptcha.SecretKey = builder.Configuration.GetRequiredValue("Captcha:HCaptcha:SecretKey");
options.Forms = CaptchaForms.Register | CaptchaForms.ForgotPassword | CaptchaForms.Login;
});
Dica
Um provedor configurado sem ambas as chaves para o portal na inicialização com uma mensagem nomeando o que está faltando, em vez de começar com formulários que recusariam todos os visitantes.
Adicionando o desafio aos seus próprios formulários
As páginas de conta do modelo já o carregam. Em um formulário seu, coloque o Captcha componente — ele não renderiza nada a menos que o formulário que você nomear exija um desafio — e envie o token que ele entrega quando o formulário for enviado: TakeTokenAsync() no Blazor, takeToken() no árbitro no React. Uma submissão que o servidor recusou para o desafio surge CaptchaVerificationException em Blazor e CaptchaVerificationError no React.
const captcha = useRef<CaptchaHandle>(null);
const register = async () => {
try {
await auth.registerAsync({ email, password, captchaToken: (await captcha.current?.takeToken()) ?? null });
} catch (error) {
// Diz ao visitante para resolver o desafio novamente e o reseta.
if (error instanceof CaptchaVerificationError) captcha.current?.reportNotSolved();
}
};
<Captcha ref={captcha} form={CaptchaForms.Register} /><Captcha @ref="_captcha" Form="CaptchaForms.Register" />
@code {
private Captcha? _captcha;
private async Task RegisterAsync()
{
try
{
await AuthService.RegisterAsync(new RegisterRequest
{
Email = _email,
Password = _password,
CaptchaToken = await _captcha!.TakeTokenAsync(),
});
}
catch (CaptchaVerificationException)
{
// Diz ao visitante para resolver o desafio novamente e o reseta.
await _captcha!.ReportNotSolvedAsync();
}
}
}Um token é válido para uma submissão, então pegá-lo também reinicia o desafio: qualquer que seja o resultado — uma senha errada, um endereço já em uso — a próxima tentativa recebe uma nova sem que a página faça nada. No reCAPTCHA v3 não há token até que ele seja tomado, então não segure o botão de enviar até TokenChanged que (Blazor) ou onTokenChange (React) reportem um.
Uma página Blazor renderizada pelo servidor que se chama UserManager , em vez de passar por IAuthService, verifica o token com ICaptchaVerifier antes de agir:
@inject ICaptchaVerifier CaptchaVerifier
if (!await CaptchaVerifier.VerifyAsync(CaptchaForms.Register, await _captcha!.TakeTokenAsync()))
{
await _captcha!.ReportNotSolvedAsync();
return;
}
Limitando tentativas por endereço
Independentemente de um CAPTCHA estar configurado ou não, o portal limita a frequência com que um endereço envia cada formulário que alguém pode enviar sem fazer login — login, cadastro, redefinição de senha, reenvio de confirmação, aceitação de convite. Por padrão, um endereço pode enviar cada endereço 20 vezes por minuto; além disso, ele é respondido com 429 Too Many Requests até o minuto acabar. Cada formulário é contado separadamente. Altere o limite em PowerPortalsPro:SignInRateLimit; a PermitLimit de 0 o desativa.
{
"PowerPortalsPro": {
"SignInRateLimit": {
"PermitLimit": 20,
"Window": "00:01:00"
}
}
}
Importante
O limite conta o endereço de onde vem uma solicitação. Atrás de um proxy ou gateway que não passa o endereço do visitante — Azure Front Door, Application Gateway, um balanceador de carga próprio — todo visitante chega dos proxys, e eles compartilham uma contagem. Encaminhe o endereço do visitante com
UseForwardedHeaders, nomeando o proxy emKnownProxiesouKnownNetworks.
Política de Segurança de Conteúdo
O widget é carregado a partir do site do provedor. Se seu portal enviar um Content-Security-Policy cabeçalho, permita que os hosts do provedor entrem script-src e frame-src (hCaptcha também precisa style-src de e connect-src):
| Provedor | Apresentadores |
|---|---|
Turnstile |
https://challenges.cloudflare.com |
ReCaptchaV2 |
https://www.google.com/recaptcha/, https://www.gstatic.com/recaptcha/ |
HCaptcha |
https://hcaptcha.com, https://*.hcaptcha.com |
Solução de problemas
- Toda submissão é recusada. A chave secreta está errada ou pertence a outra chave do site. O servidor registra um erro nomeando a reclamação do provedor a cada vez.
- O formulário diz que o desafio não pôde ser carregado. O script do provedor foi bloqueado — por uma extensão do navegador, um filtro de rede ou uma Política de Segurança de Conteúdo — ou o navegador está offline.
- O widget mostra um erro sobre o domínio. O nome de host de onde o portal é servido não está na lista do provedor para essa chave do site.
- Um desafio resolvido é recusado. Tokens expiram após alguns minutos e podem ser usados uma vez. O widget geralmente se renova; se um visitante deixar o formulário aberto, ele o resolve novamente.
- O portal não inicia após definir um provedor. O de
SiteKeyesse provedor ouSecretKeyestá faltando — sobCaptcha:Turnstile,Captcha:ReCaptchaV2,Captcha:ReCaptchaV3ouCaptcha:HCaptcha— ou, para reCAPTCHA v3,MinimumScorenão está entre 0 e 1. O erro de inicialização diz quais opções falharam.
