Como personalizar a página de login do WordPress em 2026 (completo)

Como personalizar a página de login do WordPress em 2026 (completo)

Última verificação: 14 de outubro de 2026
22 min de leitura
Guia
Auditor de segurança
Desenvolvedor full-stack

O ecrã de login padrão do WordPress (wp-login.php) reconhece-se em três segundos: fundo cinzento, logótipo do WordPress, formulário genérico. Para um blog pessoal serve. Para uma loja, um portal de clientes ou um projeto de agência com a marca do cliente, é uma falha de branding. Os editores entram todos os dias, e a primeira impressão não é a página inicial, é este ecrã.

Este guia mostra como adaptar o login à marca apenas com hooks do WordPress: login_enqueue_scripts, os filtros do logótipo login_headerurl e login_headertext, login_message, mensagens de erro genéricas e a escolha entre plugin must-use e tema filho. Todos os hooks e versões foram verificados no código-fonte do WordPress 7.1. Para reforço que vai além do aspeto visual, veja os nossos serviços de segurança WordPress.

#O que o WordPress carrega no wp-login.php

Antes de trocar o logótipo, convém saber o que o núcleo faz quando alguém pede wp-login.php:

  1. Carrega wp-admin/css/login.css e os estilos do painel de que depende (botões, formulários).
  2. Dispara login_enqueue_scripts, onde adiciona o seu CSS e JS, tal como wp_enqueue_scripts no front-end.
  3. Desenha o cabeçalho com a ligação do logótipo (por defeito para wordpress.org), o formulário, as ligações de palavra-passe esquecida e de registo, e o rodapé.
  4. Num erro de validação, acrescenta o script de abanar e mostra a mensagem do filtro login_errors.
  5. Os filtros login_message e login_messages permitem colocar HTML por cima do formulário (aviso depois de terminar sessão, nota de manutenção, banner de SSO).

A consequência principal: a página de login não passa pelo pipeline do tema do front-end. header.php, os modelos de um tema de blocos e a maioria dos callbacks de wp_enqueue_scripts não correm ali. Por isso existe uma ação de enqueue própria e por isso os estilos do login precisam de um ficheiro próprio. Regras que só estão no style.css do tema nunca chegam ao wp-login.php.

A segunda consequência: uma atualização do WordPress pode mudar seletores, a ordem dos scripts ou o markup do formulário (campos extra de um plugin de 2FA, por exemplo). Branding construído com hooks sobrevive à atualização; um wp-login.php alterado no núcleo não.

#Como carregar um CSS próprio na página de login do WordPress

O fundo cinzento padrão (#f0f0f1 no login.css atual) raramente combina com a marca. Crie um ficheiro style-login.css no tema e carregue-o só na página de login, com número de versão para que o navegador não use a cópia antiga em cache depois de um deploy:

function wppoland_login_stylesheet() {
	wp_enqueue_style(
		'wppoland-login',
		get_stylesheet_directory_uri() . '/style-login.css',
		array(),
		wp_get_theme()->get( 'Version' )
	);
}
add_action( 'login_enqueue_scripts', 'wppoland_login_stylesheet' );

Exemplo style-login.css:

body.login {
	background-color: #0d1117;
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 100vh;
	font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.login form {
	background: #161b22;
	border: 1px solid #30363d;
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
	border-radius: 12px;
	padding: 40px;
}

.login label {
	color: #c9d1d9;
	font-size: 14px;
	font-weight: 500;
}

.login input[type="text"],
.login input[type="password"] {
	background: #0d1117;
	border: 1px solid #30363d;
	border-radius: 6px;
	color: #c9d1d9;
	padding: 12px 16px;
	font-size: 14px;
}

.login input[type="text"]:focus,
.login input[type="password"]:focus {
	border-color: #58a6ff;
	box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.4);
}

.wp-core-ui .button-primary {
	background: #238636;
	border-color: rgba(27, 31, 35, 0.15);
	border-radius: 6px;
	padding: 12px 24px;
	font-size: 14px;
	font-weight: 600;
	text-shadow: none;
	box-shadow: none;
}

.wp-core-ui .button-primary:hover,
.wp-core-ui .button-primary:focus {
	background: #2ea043;
}

.login #nav,
.login #backtoblog {
	text-align: center;
}

.login #nav a,
.login #backtoblog a {
	color: #8b949e;
}

.login #nav a:hover,
.login #backtoblog a:hover {
	color: #58a6ff;
}

Regras práticas para o CSS do login:

  • Aponte para classes que o WordPress realmente emite: body.login, #login, .login form, .wp-core-ui .button-primary, #login_error, .message.
  • Não esconda #nav e #backtoblog sem acordo com o cliente. Os editores perdem o caminho de volta ao site e a recuperação da palavra-passe parece avariada.
  • Evite display: none em campos do formulário. Um plugin de 2FA ou de passkeys acrescenta campos próprios, e escondidos por CSS parecem um login avariado.
  • Teste o contraste (WCAG) das mensagens de erro e das etiquetas. Fundo escuro com texto cinzento chumba muitas vezes em auditorias de acessibilidade. Não retire o contorno de foco sem substituto: no exemplo acima, um box-shadow bem visível faz esse papel.

Se precisar das fontes do cliente, carregue-as aqui ou aloje-as localmente no tema. Um terceiro domínio no ecrã de login é um pedido a mais e mais um ponto de falha de DNS.

#Como mudar o logótipo da página de login do WordPress

O WordPress não tem um filtro que troque o ficheiro do logótipo. O padrão habitual é CSS em #login h1 a como imagem de fundo, mais dois filtros para os atributos da ligação.

function wppoland_login_logo() {
	$logo = get_stylesheet_directory_uri() . '/images/logotipo-cliente.svg';
	?>
	<style type="text/css">
		#login h1 a,
		.login h1 a {
			background-image: url(<?php echo esc_url( $logo ); ?>);
			height: 65px;
			width: 100%;
			max-width: 320px;
			background-size: contain;
			background-repeat: no-repeat;
			background-position: center;
			padding-bottom: 30px;
		}

		@media (max-width: 768px) {
			#login h1 a,
			.login h1 a {
				height: 50px;
				max-width: 280px;
			}
		}
	</style>
	<?php
}
add_action( 'login_enqueue_scripts', 'wppoland_login_logo' );

esc_url() no caminho é obrigatório, mesmo quando o URL vem de get_stylesheet_directory_uri(). Use SVG ou PNG com transparência. Um JPEG com margem branca parece um autocolante num formulário escuro. A media query reduz o logótipo em ecrãs estreitos para não empurrar o formulário para baixo.

A ligação padrão do logótipo vai para wordpress.org. Aponte-a para a página inicial e defina o texto acessível da ligação com o nome do site:

function wppoland_login_logo_url() {
	return home_url( '/' );
}
add_filter( 'login_headerurl', 'wppoland_login_logo_url' );

function wppoland_login_logo_url_title() {
	return get_bloginfo( 'name' );
}
add_filter( 'login_headertext', 'wppoland_login_logo_url_title' );

login_headertext substituiu login_headertitle, marcado como obsoleto desde o WordPress 5.2. Snippets antigos ainda o usam.

Em instalações com um domínio próprio para o painel (cms.cliente.pt ao lado de www.cliente.pt), home_url() continua a apontar para o site público, o que costuma ser o pretendido. Se o logótipo deve levar a documentação interna ou ao fornecedor de identidade, devolva um URL HTTPS completo e teste numa janela privada.

#Como mostrar uma mensagem por cima do formulário de login do WordPress

O filtro login_message coloca HTML por cima do formulário. Usos comuns em produção:

  • Um aviso de manutenção («Esta noite não é possível entrar fora da VPN»).
  • Uma indicação para editores («Use a conta da empresa, não uma pessoal»).
  • Um banner depois de terminar sessão ou de repor a palavra-passe (o núcleo também acrescenta ali as suas próprias classes de mensagem).
  • Uma ligação para SSO quando o fornecedor de identidade convive com as palavras-passe clássicas.
/**
 * Mensagem por cima do formulário de login.
 *
 * @param string $message HTML existente.
 * @return string
 */
function wppoland_login_message( $message ) {
	$notice = '<p class="message">' . esc_html__(
		'Contas apenas para a equipa editorial. Em caso de suspeita de fuga de palavra-passe, avise a equipa de TI.',
		'wppoland'
	) . '</p>';

	return $notice . $message;
}
add_filter( 'login_message', 'wppoland_login_message' );

Notas de implementação:

  • Escape o texto (esc_html__), ou construa o markup com wp_kses_post se precisar de uma ligação.
  • Não substitua $message às cegas. O núcleo coloca ali os seus próprios avisos (depois de loggedout=true, por exemplo). Acrescente o seu texto antes, ou filtre conforme o pedido.
  • A classe .message já tem estilo no login.css. O seu style-login.css deve respeitá-la (cor do texto, margem esquerda), ou o banner desaparece no fundo.

Para textos que dependem da ação (login, lostpassword, rp), verifique $_GET['action'] em vez de mostrar a mesma nota na recuperação da palavra-passe e no passo de 2FA.

#Como adicionar conteúdo abaixo do formulário de login

Para uma nota de suporte por baixo do formulário, use a ação login_footer:

function wppoland_login_footer_content() {
	?>
	<div class="login-footer-content">
		<p><?php echo esc_html__( 'Problemas a entrar? Contacte o suporte da sua agência.', 'wppoland' ); ?></p>
		<p>&copy; <?php echo esc_html( wp_date( 'Y' ) . ' ' . get_bloginfo( 'name' ) ); ?></p>
	</div>
	<?php
}
add_action( 'login_footer', 'wppoland_login_footer_content' );

O estilo de .login-footer-content pertence ao style-login.css, não a um bloco <style> embutido. Assim todas as regras do login ficam num só ficheiro com controlo de versões.

#Como aplicar as cores da marca do cliente com variáveis CSS

Agências que usam o mesmo modelo de login para vários clientes ganham em manter as cores como variáveis CSS num só sítio:

function wppoland_agency_branding() {
	$primary   = sanitize_hex_color( '#0073aa' ); // Cor primária do cliente
	$secondary = sanitize_hex_color( '#005177' ); // Cor secundária
	?>
	<style type="text/css">
		:root {
			--brand-primary: <?php echo esc_attr( $primary ); ?>;
			--brand-secondary: <?php echo esc_attr( $secondary ); ?>;
		}

		body.login {
			background: linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-secondary) 100%);
		}

		.wp-core-ui .button-primary {
			background: var(--brand-primary);
			border-color: var(--brand-primary);
		}

		.wp-core-ui .button-primary:hover {
			background: var(--brand-secondary);
			border-color: var(--brand-secondary);
		}
	</style>
	<?php
}
add_action( 'login_enqueue_scripts', 'wppoland_agency_branding' );

Se as cores passarem a vir de uma opção ou do Personalizador, sanitize_hex_color() (no formatting.php desde o WordPress 3.4, por isso disponível também na página de login) garante que só valores hexadecimais válidos chegam ao CSS.

#Como tornar genéricas as mensagens de erro do login

A mensagem padrão para uma palavra-passe errada pode revelar que existe um utilizador com aquele nome. Isso facilita a enumeração de contas antes de um ataque de força bruta. O filtro login_errors devolve um texto genérico:

function wppoland_login_errors() {
	return __( 'Não foi possível iniciar sessão. Verifique os seus dados e tente novamente.', 'wppoland' );
}
add_filter( 'login_errors', 'wppoland_login_errors' );

Isto dificulta o reconhecimento por parte de atacantes. Não é uma firewall, nem limitação de tentativas, nem 2FA. Continua a precisar de:

  • limitação de tentativas no servidor, na WAF ou com um plugin mantido,
  • palavras-passe fortes e, de preferência, um segundo fator (aplicação TOTP, chave física),
  • WordPress, temas e plugins atualizados,
  • restrição de acesso a wp-admin e XML-RPC onde a política da empresa o permita (VPN, lista de IP, autenticação HTTP no staging).

Muitos tutoriais mostram bloqueios de login próprios com transients em login_init e verificações de nonce no filtro authenticate. Não as recomendamos. login_init corre em cada pedido a wp-login.php, incluindo a reposição da palavra-passe, e um wp_die() ali bloqueia precisamente esse caminho. O filtro authenticate também verifica entradas por XML-RPC, palavras-passe de aplicação (wp_authenticate_application_password está ligado a este filtro com prioridade 20, segundo o default-filters.php) e wp_signon() de plugins como o WooCommerce, que não enviam esse campo de nonce. Uma verificação de nonce com prioridade 30 parte esses caminhos de entrada.

Outro pedido frequente: «escondemos o login e fica seguro». Porque não funciona:

  1. Segurança por obscuridade: bots e scanners conhecem os caminhos padrão. Um URL diferente sem controlo de acesso real estraga sobretudo os marcadores dos editores.
  2. CSS não esconde nada no servidor: display: none numa ligação de login no menu não remove o endpoint. wp-login.php e wp-admin continuam a responder.
  3. O filtro login_url muda só as ligações que o WordPress gera, não o endpoint. Mudar o login a sério exige configuração no servidor ou um plugin mantido, e depois testes à reposição da palavra-passe, à conta do WooCommerce, à REST e ao cron.
  4. Respostas REST e XML-RPC podem revelar utilizadores independentemente do branding do ecrã.

Branding do login e segurança são dois trabalhos distintos. O white-label melhora a experiência e a confiança. A proteção das contas vem de permissões, limites de tentativas, 2FA e atualizações.

#Como estilizar os campos Two Factor na página de login

Construir 2FA no functions.php é o projeto errado. Use um plugin mantido, por exemplo o Two Factor do diretório WordPress.org (versão 0.17.0, mais de 100 000 instalações ativas segundo a API do diretório em outubro de 2026), e adapte os seus campos ao branding.

Classes que este plugin emite de facto no segundo passo do login (verificadas no código da versão 0.17.0):

  • .two-factor-prompt para o parágrafo de instruções,
  • input.authcode (com id="authcode") para o código TOTP, o código por email e o código de reserva; o campo tem inputmode="numeric" e autocomplete="one-time-code", por isso não substitua esses atributos com um script, ou o telemóvel deixa de sugerir o código do SMS ou do gestor de palavras-passe,
  • .backup-methods-wrap para as ligações aos métodos alternativos,
  • .two-factor-email-resend para o botão que reenvia o código por email.
.login .two-factor-prompt {
	color: #c9d1d9;
}

.login input.authcode {
	background: #0d1117;
	border: 1px solid #30363d;
	color: #c9d1d9;
	letter-spacing: 0.2em;
	text-align: center;
}

.login .backup-methods-wrap a {
	color: #c9d1d9;
}

Seletores como .two-factor-methods ou .passkey-button, que circulam em tutoriais antigos, não existem no código atual do plugin, e regras para eles nunca se aplicam. Outros plugins de 2FA e passkeys têm markup próprio: leia os seletores no código de cada um.

Se os administradores sem 2FA configurado devem ir diretamente para a configuração depois do login, use o filtro login_redirect com o método público do plugin:

function wppoland_2fa_setup_redirect( $redirect_to, $requested_redirect_to, $user ) {
	if ( ! $user instanceof WP_User || ! class_exists( 'Two_Factor_Core' ) ) {
		return $redirect_to;
	}

	if ( user_can( $user, 'manage_options' ) && ! Two_Factor_Core::is_user_using_two_factor( $user->ID ) ) {
		return admin_url( 'profile.php#two-factor-options' );
	}

	return $redirect_to;
}
add_filter( 'login_redirect', 'wppoland_2fa_setup_redirect', 10, 3 );

Two_Factor_Core::is_user_using_two_factor() e a âncora #two-factor-options no perfil vêm do código do plugin. user_can() verifica o utilizador recebido; current_user_can() estaria errado aqui, porque o utilizador atual ainda não está definido durante o filtro. Isto não obriga ninguém a usar 2FA, apenas encaminha para a configuração no momento do login.

#Como remover o efeito shake no login do WordPress

Quando o login falha, o formulário abana. Alguns clientes acham isto pouco profissional.

O snippet que a maioria dos tutoriais ainda copia, remove_action( 'login_head', 'wp_shake_js', 12 ), não faz nada desde o WordPress 5.4. O núcleo liga agora wp_shake_js a login_footer, e só de forma condicional, dentro de login_header(). Vê-se no wp-login.php do repositório wordpress-develop; o ramo 5.3 ainda usava login_head. O método estável é o filtro shake_error_codes, disponível desde a 3.0: uma lista vazia de códigos de erro significa nenhuma animação.

add_filter( 'shake_error_codes', '__return_empty_array' );

O filtro é API pública e não depende da prioridade nem do hook em que o núcleo imprime o script.

#Como comparar plugins de login personalizado

Quem não quer manter o login em código encontra vários plugins no diretório WordPress.org. Dados da API de plugins do WordPress.org a 14 de outubro de 2026:

PluginVersãoInstalações ativasFoco
LoginPress6.2.5200 000+Editor visual para o wp-login.php
Custom Login Page Customizer2.5.490 000+Desenho no Personalizador
Theme My Login7.3.150 000+Páginas de login no front-end

O plugin Login Designer, muito citado antes, está agora fechado no diretório e não deve ser instalado de novo. Não junte um plugin aos hooks deste guia: duas fontes a estilizar #login h1 a sobrepõem-se. Escolha código ou plugin.

#Plugin must-use ou tema filho para o código do login

Onde guardar o código? Há dois sítios sensatos e um errado.

Tema filho (functions.php e style-login.css)

  • Vantagens: logótipo e cores acompanham o design do front-end; o designer altera ficheiros num só repositório; versão controlada pelo campo Version do style.css.
  • Desvantagens: uma troca de tema (avaria, teste A/B, migração para um tema de blocos) desliga o branding do login. Num multisite com temas diferentes por site, o código tem de ser duplicado ou subir de nível, veja a nossa arquitetura multisite.

Plugin must-use (wp-content/mu-plugins/wppoland-login-branding.php)

  • Vantagens: funciona independentemente do tema ativo, ideal para redes de agência e instalações cujo tema muda; difícil de desativar por acidente no painel.
  • Desvantagens: os ficheiros (logótipo, CSS) carregam-se a partir da pasta do plugin (plugin_dir_url( __FILE__ )); o deploy de plugins must-use costuma ficar esquecido em fluxos que só publicam o tema.

O sítio errado: alterações em wp-admin/ ou um patch ao wp-login.php do núcleo. Ambos desaparecem na atualização seguinte. Evite também plugins de snippets que guardam PHP na base de dados sem controlo de versões: na migração de staging para produção os snippets perdem-se ou duplicam-se.

<?php
/**
 * Plugin Name: WPPoland Login Branding
 * Description: White-label do wp-login.php independente do tema.
 * Author: wppoland.com
 */

defined( 'ABSPATH' ) || exit;

add_action( 'login_enqueue_scripts', function () {
	wp_enqueue_style(
		'wppoland-login',
		plugin_dir_url( __FILE__ ) . 'assets/style-login.css',
		array(),
		'2026.10.14'
	);
} );

add_filter( 'login_headerurl', function () {
	return home_url( '/' );
} );

add_filter( 'login_headertext', function () {
	return get_bloginfo( 'name' );
} );

Regra de decisão para o briefing: se o branding do login faz parte do produto do cliente (cores da marca, logótipo de campanha), vai para o tema filho. Se é um padrão da agência em muitas instalações (o mesmo logótipo da agência em todos os staging, erros genéricos, sem abanar), vai para um plugin must-use ou para um pacote Composer partilhado publicado em todos os ambientes.

#Como personalizar o login do WooCommerce e de plugins de membros

As páginas de conta do WooCommerce e os blocos de login no checkout usam um markup diferente do wp-login.php. O CSS do ecrã de login não altera os formulários em my-account. Ou aceita os formulários padrão do Woo, ou carrega uma folha de estilos própria nesses templates. Misturar as duas coisas em style-login.css deixa regras mortas e confunde o próximo programador.

A mesma separação vale para o LearnDash, o MemberPress e produtos semelhantes: primeiro identifique o endereço por onde os clientes entram de facto, depois aplique a marca a essa superfície. Um erro típico de agência é afinar o wp-login.php enquanto os clientes só veem um modal no front-end que, dentro de um iframe, continua a mostrar o logótipo do WordPress.

#Como verificar a página de login depois de atualizar o núcleo do WordPress

As versões maiores do WordPress alteram de vez em quando o markup ou o CSS por omissão do login. Depois de atualizar o núcleo no staging:

  1. Se algo parecer estranho, compare o HTML do login com a versão anterior à atualização.
  2. Volte a verificar o tamanho do logótipo; novas alturas por omissão podem cortar SVGs.
  3. Se desativou o efeito shake, confirme que o filtro shake_error_codes continua a aplicar-se.
  4. Volte a testar os campos de 2FA se esse plugin foi atualizado na mesma altura.

Associe a versão da folha de estilos à versão do tema ou do plugin, para que os browsers não guardem um style-login.css antigo depois de corrigir um problema de contraste.

#Que hooks de login o WordPress oferece e desde que versão

A tabela vem das etiquetas @since em src/wp-login.php no repositório wordpress-develop (outubro de 2026, versão atual WordPress 7.1.3). Ajuda quando um cliente mantém uma instalação antiga ou quando um snippet de fórum usa um hook que ainda não existe ou que já está obsoleto.

HookTipoDesdePara que serve
login_headerurlfiltro2.1.0URL da ligação do logótipo
login_messagefiltro2.1.0HTML por cima do formulário
login_errorsfiltro2.1.0texto dos erros
login_messagesfiltro2.5.0avisos informativos
login_redirectfiltro3.0.0destino do redirecionamento após o login
shake_error_codesfiltro3.0.0códigos de erro que fazem abanar o formulário
login_enqueue_scriptsação3.1.0CSS e JS do ecrã de login
login_footeração3.1.0conteúdo no rodapé
login_initação3.2.0início do processamento do pedido
login_body_classfiltro3.5.0classes do elemento body
login_headeração4.6.0conteúdo logo após a abertura do body
login_titlefiltro4.9.0conteúdo da etiqueta title
login_link_separatorfiltro4.9.0separador das ligações sob o formulário
login_headertextfiltro5.2.0texto da ligação do logótipo
login_site_html_linkfiltro5.7.0ligação de regresso ao site no rodapé
login_display_language_dropdownfiltro5.9.0se o seletor de idioma aparece
login_language_dropdown_argsfiltro5.9.0argumentos da lista de idiomas

login_headertitle (desde 2.1.0) está obsoleto desde a 5.2.0 e passa por apply_filters_deprecated, por isso com WP_DEBUG ativo deixa um aviso no registo. Se o tema de um cliente ainda o usa, mude para login_headertext.

#Como mudar o título, a classe do body e o seletor de idioma no wp-login.php

Quatro filtros da tabela resolvem pedidos pequenos do briefing sem tocar no CSS:

// Título do separador mais curto: nome do ecrã e nome do site.
add_filter( 'login_title', function ( $login_title, $title ) {
	return $title . ' | ' . get_bloginfo( 'name', 'display' );
}, 10, 2 );

// Classe própria no body para as regras do login não colidirem com outras folhas de estilo.
add_filter( 'login_body_class', function ( $classes ) {
	$classes[] = 'wppoland-login';
	return $classes;
} );

// A ligação do rodapé leva a uma página de ajuda em vez da página inicial.
add_filter( 'login_site_html_link', function () {
	return sprintf(
		'<a href="%s">%s</a>',
		esc_url( home_url( '/ajuda/' ) ),
		esc_html__( 'Ajuda para editores', 'wppoland' )
	);
} );

// Sem lista de idiomas por baixo do formulário.
add_filter( 'login_display_language_dropdown', '__return_false' );

Pormenores que só aparecem no código do núcleo:

  • O título padrão junta o nome do ecrã, o nome do site e a palavra WordPress no fim. No modo de recuperação, o núcleo acrescenta um prefixo antes de chamar o filtro. Um callback que constrói o título só a partir de $title perde esse prefixo, e o administrador deixa de ver no separador que o site está em modo de recuperação. Se isso importa, altere $login_title em vez de o substituir.
  • A lista de idiomas só aparece quando existe pelo menos um pacote de idioma adicional instalado, e nunca na janela de novo login do painel. Escondê-la não muda o idioma da conta: depois do login aplica-se a definição do perfil.
  • login_site_html_link substitui o elemento <a> inteiro, por isso o escape do URL e do texto fica a seu cargo.
  • A ligação para a política de privacidade por baixo do formulário vem de the_privacy_policy_link() e aparece quando há uma página de privacidade definida. Não a esconda com CSS em sites que recolhem dados através de um formulário de registo.

#Que cabeçalhos de segurança o WordPress envia no wp-login.php

Antes de acrescentar cabeçalhos ou meta tags próprios ao ecrã de login, veja o que o núcleo já faz. Segundo o default-filters.php e o wp-login.php:

  • send_frame_options_header() em login_init (desde 3.1.3) envia X-Frame-Options: SAMEORIGIN, e desde o WordPress 6.9 a mesma função acrescenta Content-Security-Policy: frame-ancestors 'self'. O ecrã de login não pode ser incorporado numa moldura de outro domínio.
  • wp_admin_headers() em login_init (desde 4.9) envia Referrer-Policy: strict-origin-when-cross-origin; o filtro admin_referrer_policy muda o valor.
  • wp_robots_sensitive_page() (desde 5.7) acrescenta noindex e noarchive à meta robots, impressa por wp_robots em login_head.
  • wp_strict_cross_origin_referrer() (desde 5.7) acrescenta uma meta tag referrer com a mesma política.
  • wp_site_icon em login_head imprime o favicon definido em Ícone do site.

Na prática, um snippet que imprime uma meta robots noindex ou uma ligação de favicon em login_head só duplica etiquetas. Não acrescente X-XSS-Protection. A MDN descreve este cabeçalho como não normalizado e obsoleto, avisa que pode criar vulnerabilidades XSS em sites de outro modo seguros e recomenda Content-Security-Policy. Cabeçalhos para todo o site (HSTS, CSP) pertencem à configuração do servidor ou da CDN, não a PHP em login_init, para cobrirem também wp-admin e a REST.

#Como resolver problemas comuns no login personalizado

CSS não está a ser aplicado

  • Verificar o caminho do ficheiro CSS (o nome no código e no tema tem de coincidir)
  • Subir o número de versão no enqueue ou limpar a cache do navegador
  • Verificar a prioridade dos hooks

Logótipo não aparece

  • Verificar as permissões do ficheiro
  • Em SVG, confirmar que o servidor envia o tipo MIME image/svg+xml
  • Verificar o caminho com get_stylesheet_directory_uri()

Redirecionamentos em loop

Conflitos com plugins de segurança

  • Testar um plugin de cada vez
  • Verificar a ordem de carregamento dos hooks
  • Consultar a documentação do plugin

#Como testar o branding do login no staging

Numa cópia da produção, siga esta ordem:

  1. Carregue o CSS e o logótipo; abra wp-login.php sem cache (janela privada).
  2. Clique no logótipo: chega ao site do cliente, não a wordpress.org.
  3. Entre com uma conta válida, termine sessão, entre com a palavra-passe errada: a mensagem é genérica.
  4. Teste a recuperação da palavra-passe e o email de reposição num ambiente com SMTP configurado.
  5. Se houver 2FA, percorra o fluxo completo uma vez no computador e outra no telemóvel.
  6. Mude temporariamente para um tema padrão: se o branding desaparece e devia ser global, passe o código para um plugin must-use.
  7. Registe no README do projeto os caminhos dos ficheiros e a lista de filtros, para que o próximo programador não procure a lógica em cinco plugins de snippets.

Depois da aprovação do cliente, repita o mesmo teste rápido em produção logo após o deploy.

#Resumo

Uma página de login personalizada é pouco código com grande efeito na impressão que um projeto deixa.

Pontos-chave:

  • Marca: logótipo, ligação para a página inicial, texto da ligação via login_headertext
  • Estilo: style-login.css próprio e com versão, via login_enqueue_scripts
  • Segurança: mensagens de erro genéricas, 2FA para administradores, limitação de tentativas no servidor ou na WAF
  • Abanar: shake_error_codes em vez do remove_action desatualizado
  • Localização: tema filho ou plugin must-use, nunca ficheiros do núcleo

Entregue ao cliente uma nota de uma página: onde está o código, como se troca o logótipo e qual é o URL de login da equipa. Veja os nossos serviços de segurança WordPress.

Próximo passo

Transforme o artigo numa implementação real

Este bloco reforça a ligação interna e conduz o leitor para o passo seguinte mais útil dentro da arquitetura do site.

Cluster relacionado

Explorar outros serviços WordPress e base de conhecimento

Reforce o seu negócio com suporte técnico profissional em áreas-chave do ecossistema WordPress.

Como mudar o logótipo do login do WordPress sem plugin?#
Ligue uma função a login_enqueue_scripts, imprima CSS para #login h1 a com o logótipo do cliente a partir do tema filho ou de um plugin must-use e aponte a ligação do logótipo para a página inicial com login_headerurl.
Porque é que remove_action no wp_shake_js não tira o efeito shake?#
Desde o WordPress 5.4 o núcleo liga o wp_shake_js a login_footer e não a login_head. O método estável é o filtro shake_error_codes com um array vazio.
Onde deve ficar o código de personalização do login?#
No tema filho, quando o branding faz parte do produto do cliente, ou num plugin must-use, quando tem de sobreviver a uma troca de tema. Nunca nos ficheiros do núcleo.
Mensagens de erro genéricas travam ataques de força bruta?#
Não. Dificultam a enumeração de utilizadores, mas continua a precisar de limitação de tentativas no servidor ou na WAF, palavras-passe fortes e 2FA para administradores.
É preciso acrescentar meta robots noindex ao wp-login.php?#
Não. Desde o WordPress 5.7 o núcleo já acrescenta noindex e noarchive ao ecrã de login, e um snippet próprio só duplica a etiqueta.

Precisa de FAQ adaptado ao setor e mercado? Criamos uma versão alinhada com os seus objetivos de negócio.

Fale connosco

Artigos Relacionados