Redirecionar HTTP para HTTPS com .htaccess (redirecionamento 301)

Publicado a Atualizado a 4 min de leitura

Os visitantes continuam a aterrar na versão não encriptada? Com poucas linhas no ficheiro .htaccess envia cada pedido HTTP para HTTPS de forma permanente, com um redirecionamento 301.

O seu servidor já entrega o site através de HTTPS, mas os visitantes continuam a aterrar na versão HTTP não encriptada? Então falta um redirecionamento. Neste guia configura, com um ficheiro .htaccess, um redirecionamento permanente (código de estado 301) de HTTP para HTTPS.

Um redirecionamento 301 também é a escolha certa do ponto de vista do SEO: os motores de busca transferem assim o posicionamento do antigo endereço HTTP para o endereço HTTPS, em vez de tratarem as duas variantes como páginas separadas.

Requisitos

  • No seu servidor corre o Apache. Para o nginx aplica-se uma configuração diferente, tratada mais abaixo.
  • Já tem um certificado SSL válido instalado. Se ainda não for o caso, encontra o guia adequado no artigo Configurar um certificado SSL gratuito com Let's Encrypt.
  • Tem acesso ao diretório web do seu servidor, por SSH ou por FTP.

Importante: configure o redirecionamento apenas depois de o HTTPS funcionar. Caso contrário, envia os visitantes para um endereço que apresenta um aviso de certificado.

Ativar o mod_rewrite e permitir o ficheiro .htaccess

O redirecionamento assenta no módulo do Apache mod_rewrite. Ative-o e reinicie o Apache:

a2enmod rewrite
systemctl restart apache2

Para que o Apache sequer leia o ficheiro .htaccess, o VirtualHost tem de o permitir. Verifique na configuração, em /etc/apache2/sites-available/, se AllowOverride All está definido para o seu diretório:

<Directory /var/www/MeuDominio.com>
    AllowOverride All
    Require all granted
</Directory>

Se aí estiver AllowOverride None, o seu ficheiro .htaccess é ignorado em silêncio. Depois de uma alteração ao ficheiro do VirtualHost é necessário reiniciar o Apache.

Criar o ficheiro .htaccess

Mude para o diretório onde está o seu site:

cd /var/www/<SEU-DIRETORIO-WEB>

Abra o ficheiro .htaccess no editor. Se ainda não existir, o comando cria-o:

nano .htaccess

Introduza as linhas seguintes. Esta variante verifica diretamente se a ligação está encriptada e acrescenta ao destino o caminho completo que foi pedido:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Guarde o ficheiro com "CTRL + X", depois "Y" e "Enter".

Alternativa através da porta do servidor

Em configurações mais antigas, nas quais a variável HTTPS não é definida, funciona em alternativa a consulta da porta:

RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]

Variante atrás de um reverse proxy ou load balancer

Se à frente do seu Apache estiver um reverse proxy ou um load balancer que termina ele próprio a encriptação, o Apache recebe um pedido não encriptado. A regra acima redirecionaria então sem fim. Nesse caso, avalie o cabeçalho que o proxy envia:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Testar o redirecionamento

Abra o seu domínio no navegador através de http://. Deve aterrar de imediato em https://. Na linha de comandos verifica o código de estado diretamente:

curl -I http://MeuDominio.com

Na saída tem de constar HTTP/1.1 301 Moved Permanently, além de uma linha Location com o endereço HTTPS. Se em vez disso aparecer um código de estado 302, verifique se a regra contém mesmo R=301.

Ativar o HSTS (opcional)

Com o HTTP Strict Transport Security indica ao navegador que não deve voltar a chamar o seu domínio por HTTP. Assim desaparece o primeiro pedido sem proteção. Ative primeiro o módulo necessário:

a2enmod headers
systemctl restart apache2

De seguida, acrescente ao ficheiro .htaccess:

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

Tenha em conta o seguinte: o HSTS é um compromisso de um ano. Enquanto o valor estiver guardado no navegador, o domínio deixa de estar acessível por HTTP. Defina o cabeçalho apenas quando o HTTPS funcionar de forma fiável e todos os subdomínios tiverem também um certificado válido.

Erros frequentes

  • Ciclo infinito ("too many redirects"): quase sempre é consequência de um proxy colocado à frente. Utilize a variante com X-Forwarded-Proto.
  • Não acontece nada: ou o mod_rewrite não está ativo, ou o VirtualHost não permite ficheiros .htaccess (AllowOverride None).
  • Erro 500 depois de guardar: um erro de escrita no ficheiro .htaccess. O motivo exato consta do log de erros do Apache, em /var/log/apache2/error.log.
  • Conteúdo misto: a página até carrega por HTTPS, mas continua a incluir imagens ou scripts por HTTP. Corrija esses endereços no seu código-fonte ou na base de dados.
  • O ficheiro não aparece: o ficheiro .htaccess começa por um ponto e por isso está oculto. Com ls -la consegue vê-lo.

Redirecionamento sem .htaccess

Um ficheiro .htaccess é lido de novo em cada pedido. Se tiver acesso à configuração do servidor, é mais rápido guardar as regras diretamente no VirtualHost. Para o VirtualHost de HTTP basta então:

<VirtualHost *:80>
    ServerName MeuDominio.com
    Redirect permanent / https://MeuDominio.com/
</VirtualHost>

Se utilizar nginx em vez de Apache, não existem ficheiros .htaccess. Aí o redirecionamento é indicado no bloco server da porta 80:

server {
    listen 80;
    server_name MeuDominio.com www.MeuDominio.com;
    return 301 https://$host$request_uri;
}

Perguntas frequentes

Porquê um redirecionamento 301 e não um 302?
O 301 significa um redirecionamento permanente. Os motores de busca transferem assim a avaliação do antigo endereço HTTP para o endereço HTTPS. Um 302 é considerado temporário e não passa esses sinais.
O meu ficheiro .htaccess é ignorado. A que se deve?
Ou o mod_rewrite não está ativado, ou o VirtualHost não permite overrides. Defina AllowOverride All para o seu diretório e reinicie o Apache a seguir.
Porque é que fico num ciclo infinito?
Isso acontece quase sempre quando um reverse proxy ou um load balancer termina a encriptação à frente do Apache. Nesse caso, avalie o cabeçalho X-Forwarded-Proto em vez da variável HTTPS.
Isto também funciona com nginx?
Não, o nginx não conhece ficheiros .htaccess. Aí o redirecionamento é indicado diretamente no bloco server da porta 80, com a linha return 301 https://$host$request_uri.
Devo ativar também o HSTS?
O HSTS aumenta a segurança, mas obriga-o a manter o HTTPS durante o prazo indicado. Ative-o apenas quando o HTTPS funcionar de forma fiável no domínio e em todos os subdomínios.

.htaccess Redirecionamento Redirecionamento 301 HTTPS Apache mod_rewrite HSTS