Forçar SSL / https usando .htaccess e mod_rewrite

234

Como forçar o SSL / https usando a página .htaccess e mod_rewrite específica no PHP.

Sanjay Shah
fonte

Respostas:

438

Para o Apache, você pode usar mod_sslpara forçar o SSL com o SSLRequireSSL Directive:

Esta diretiva proíbe o acesso, a menos que o HTTP sobre SSL (ou seja, HTTPS) esteja ativado para a conexão atual. Isso é muito útil dentro do host ou diretórios virtuais habilitados para SSL para se defender contra erros de configuração que expõem coisas que devem ser protegidas. Quando esta diretiva está presente, todos os pedidos são negados e não estão usando SSL.

Isso não fará um redirecionamento para https. Para redirecionar, tente o seguinte com mod_rewriteno seu arquivo .htaccess

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

ou qualquer uma das várias abordagens dadas em

Você também pode resolver isso a partir do PHP, caso seu provedor tenha desabilitado o .htaccess (o que é improvável desde que você solicitou, mas mesmo assim)

if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    if(!headers_sent()) {
        header("Status: 301 Moved Permanently");
        header(sprintf(
            'Location: https://%s%s',
            $_SERVER['HTTP_HOST'],
            $_SERVER['REQUEST_URI']
        ));
        exit();
    }
}
Gordon
fonte
1
Isso é ótimo em nossa situação, porque atualmente temos uma mistura de tráfego http e https. Para nossa área de administração, apenas inserimos o script .htaccess, mantendo o restante do site http.
Michael J. Calkins
1
Quando uso o método mod_rewrite, sou enviado para https, mas com o erro "A página não está redirecionando corretamente".
Czechnology
11
Acompanhamento: se você estiver tendo problemas semelhantes, verifique o servidor e as variáveis ​​HTTP. Se os seus usa o servidor proxies, você pode querer usar %{HTTP:X-Forwarded-Proto}ou %{HTTP:X-Real-Port}variáveis para verificar se o SSL está ligado.
Czechnology
8
Se você enfrentar loops de redirecionamento em servidores executando atrás de proxies ( CloudFlare , Openshift ), consulte esta resposta para obter uma solução que funcione também para esse caso.
Raphinesse 03/12/2015
4
@GTodorov - Remover o espaço quebrou a reescrita para mim. Do meu conhecimento (limitado) de reescritores, a sintaxe é RewriteRule <input-pattern> <output-url>. Assim, o espaço precisa estar lá, e o single ^diz apenas "corresponder a todos os URLs de entrada".
Sphinxxx
54

Encontrei uma mod_rewritesolução que funciona bem para servidores com e sem proxy.

Se você estiver usando CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift ou qualquer outra solução Cloud / PaaS e estiver enfrentando loops de redirecionamento com redirecionamentos HTTPS normais, tente o seguinte snippet.

RewriteEngine On

# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on

# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
raphinesse
fonte
Isso é thx brilhante! Mas talvez seja necessário adicionar condição pós? RewriteCond% {REQUEST_METHOD}! ^ POST $
Aleksej
@Aleksej True, isso quebra solicitações POST não criptografadas. Mas acho que isso é uma coisa boa. Dessa forma, as pessoas perceberão que estão fazendo algo errado. Acho que o melhor seria redirecioná-los para uma página que os informa sobre como usar corretamente o seu serviço.
raphinesse
@raphinesse Você sabe a resposta desta pergunta: stackoverflow.com/questions/51951082/…
RRN
36

Solução PHP

Tomando emprestado diretamente da resposta muito abrangente de Gordon, notei que sua pergunta menciona ser específico da página para forçar conexões HTTPS / SSL.

function forceHTTPS(){
  $httpsURL = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  if( count( $_POST )>0 )
    die( 'Page should be accessed with HTTPS, but a POST Submission has been sent here. Adjust the form to point to '.$httpsURL );
  if( !isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS']!=='on' ){
    if( !headers_sent() ){
      header( "Status: 301 Moved Permanently" );
      header( "Location: $httpsURL" );
      exit();
    }else{
      die( '<script type="javascript">document.location.href="'.$httpsURL.'";</script>' );
    }
  }
}

Então, tão perto do topo dessas páginas que você deseja forçar a conexão via PHP, você pode require()um arquivo centralizado contendo essas (e quaisquer outras) funções personalizadas e simplesmente executar a forceHTTPS()função.

Solução HTACCESS / mod_rewrite

Eu não implementei esse tipo de solução pessoalmente (eu costumava usar a solução PHP, como a acima, por sua simplicidade), mas o seguinte pode ser, pelo menos, um bom começo.

RewriteEngine on

# Check for POST Submission
RewriteCond %{REQUEST_METHOD} !^POST$

# Forcing HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# Forcing HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Luke Stevenson
fonte
por curiosidade, por que o RewriteCond %{REQUEST_METHOD} !^POST$?
Depoulo
12
Como os parâmetros POST não são retidos em um redirecionamento. Você pode omitir essa linha se quiser garantir que todos os envios do POST sejam seguros (todos os envios do POST não protegidos serão ignorados).
Luke Stevenson
@Lucanos - Como escrever um RewriteCond que não força um redirecionamento para http ou https quando POST? Meu .htaccess força HTTPS em determinadas páginas específicas e força HTTP no restante. No entanto, nas páginas HTTPS, existem formulários enviados à minha raiz da web. O formulário especifica o URL da ação como HTTPS. No entanto, como a raiz da web não é uma daquelas páginas especificadas para forçar HTTPS, meu .htaccess força um redirecionamento - o que significa que as variáveis ​​POST são perdidas. Como evito redirecionamentos no POST?
precisa
1
@StackOverflowNewbie: A linha RewriteCond %{REQUEST_METHOD} !^POST$deve impedir que os envios POST sejam afetados por esses redirecionamentos.
Luke Stevenson
Eu gosto desta versão do PHP. É muito melhor, pois considera um POST e lida melhor se os cabeçalhos já tiverem sido enviados.
TheStoryCoder
10

Solução baseada em modificação de reescrita:

O uso do código a seguir no htaccess encaminha automaticamente todas as solicitações http para https.

RewriteEngine on

RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Isso redirecionará suas solicitações http não www e www para a versão www de https.

Outra solução (Apache 2.4 *)

RewriteEngine on

RewriteCond %{REQUEST_SCHEME}::%{HTTP_HOST} ^http::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Isso não funciona nas versões inferiores do apache, pois a variável% {REQUEST_SCHEME} foi adicionada ao mod-rewrite desde o 2.4.

starkeen
fonte
9

Gostaria apenas de salientar que o Apache tem as piores regras de herança ao usar vários arquivos .htaccess nas profundezas do diretório. Duas armadilhas principais:

  • Somente as regras contidas no arquivo .htaccess mais profundo serão executadas por padrão. Você deve especificar a RewriteOptions InheritDownBeforediretiva (ou similar) para alterar isso. (ver pergunta)
  • O padrão é aplicado ao caminho do arquivo relativo ao subdiretório e não ao diretório superior que contém o arquivo .htaccess com a regra especificada. (ver discussão)

Isto significa que a solução global sugerida no Apache Wiki se não funcionar se você usar quaisquer outros arquivos .htaccess em subdiretórios. Eu escrevi uma versão modificada que faz:

RewriteEngine On
# This will enable the Rewrite capabilities

RewriteOptions InheritDownBefore
# This prevents the rule from being overrided by .htaccess files in subdirectories.

RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [QSA,R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e.  http://www.example.com/foo/ to https://www.example.com/foo/
lpd
fonte
0

Simples e fácil, basta adicionar o seguinte

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Saurabh Mistry
fonte
Isso é basicamente o que as pessoas em toda a Internet dizem para você fazer para forçar o https. No entanto, toda vez que faço isso, meu site inteiro fica PROIBIDO ou Você não tem permissão para visualizar. algo assim ... O que estou fazendo de errado? Eu só quero saber se você tem alguma idéia antes de postar uma pergunta sobre isso.
ThN 14/12/19
Eu tive um problema semelhante e tive que aplicar as regras ao arquivo https.conf. Veja minha resposta abaixo.
Risteard 02/07/19
-1

Este código funciona para mim

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Alexufo
fonte
-1

Simples:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.example\.com)(:80)? [NC]
RewriteRule ^(.*) https://example.com/$1 [R=301,L]
order deny,allow

substitua seu URL por example.com

Sepehr Norouzi
fonte
NÃO! O URL do site precisa ser dinâmico.
Amir Savand
-1

por apenas forçar o SSL com o Apache .htaccess, você pode usar

SSLOptions +StrictRequire
SSLRequireSSL

para redirecionar a resposta acima está correta

webdesignwien
fonte
-1

tente esse código, ele funcionará para todas as versões de URLs, como

  • website.com
  • www.website.com
  • http://website.com
  • http://www.website.com

    RewriteCond %{HTTPS} off
    RewriteCond %{HTTPS_HOST} !^www.website.com$ [NC]
    RewriteRule ^(.*)$ https://www.website.com/$1 [L,R=301]
Kashif Latif
fonte