Forza SSL / https utilizzando .htaccess e mod_rewrite


Risposte:


438

Per Apache, è possibile utilizzare mod_sslper forzare SSL con SSLRequireSSL Directive:

Questa direttiva vieta l'accesso a meno che HTTP su SSL (ovvero HTTPS) non sia abilitato per la connessione corrente. Questo è molto utile all'interno dell'host o delle directory virtuali abilitati per SSL per difendersi da errori di configurazione che espongono oggetti che dovrebbero essere protetti. Quando questa direttiva è presente, vengono negate tutte le richieste che non utilizzano SSL.

Questo non farà comunque un reindirizzamento a https. Per reindirizzare, provare quanto segue con mod_rewritenel file .htaccess

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

o uno dei vari approcci forniti a

Puoi anche risolverlo dall'interno di PHP nel caso in cui il tuo provider abbia disabilitato .htaccess (che è improbabile da quando l'hai richiesto, ma comunque)

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();
    }
}

1
Questo è fantastico nella nostra situazione perché al momento abbiamo un misto di traffico http e https. Per la nostra area di amministrazione abbiamo appena inserito lo script .htaccess mantenendo il resto del sito http.
Michael J. Calkins,

1
Quando uso il metodo mod_rewrite, vengo inviato a https ma con un errore "La pagina non sta reindirizzando correttamente".
Czechnology,

11
Seguito: se riscontri problemi simili, controlla il tuo server e le variabili HTTP. Se il server utilizza i proxy, è possibile che si desideri utilizzare %{HTTP:X-Forwarded-Proto}o %{HTTP:X-Real-Port}variabili per verificare se SSL è attivato.
Czechnology,

8
Se si verificano cicli di reindirizzamento su server in esecuzione dietro proxy ( CloudFlare , Openshift ), vedere questa risposta per una soluzione che funzioni anche per quel caso.
raphinesse,

4
@GTodorov - La rimozione dello spazio ha interrotto la riscrittura per me. Dalla mia (limitata) conoscenza dei riscrittori, la sintassi è RewriteRule <input-pattern> <output-url>. Pertanto, lo spazio deve essere lì e il singolo ^dice semplicemente "abbina tutti gli URL di input".
Sphinxxx,

54

Ho trovato una mod_rewritesoluzione che funziona bene sia per i server proxy che per quelli non proxy.

Se stai usando CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift o qualsiasi altra soluzione Cloud / PaaS e stai riscontrando loop di reindirizzamento con reindirizzamenti HTTPS normali, prova invece il frammento seguente.

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]

Questo è brillante grazie! Ma forse è necessario aggiungere la condizione post? RewriteCond% {REQUEST_METHOD}! ^ POST $
Aleksej

@Aleksej Vero, questo interrompe le richieste POST non crittografate. Ma penso che sia una buona cosa. In questo modo, le persone noteranno che stanno facendo qualcosa di sbagliato. Immagino che la cosa migliore sarebbe reindirizzarli a una pagina che li informa su come utilizzare correttamente il tuo servizio.
raphinesse

@raphinesse Sai la risposta di questa domanda: stackoverflow.com/questions/51951082/...
RRN

36

Soluzione PHP

Prendendo in prestito direttamente dalla risposta molto esaustiva di Gordon, noto che la tua domanda menziona la specificità della pagina nel forzare connessioni 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>' );
    }
  }
}

Quindi, vicino alla parte superiore di queste pagine che si desidera forzare a connettersi tramite PHP, è possibile require()un file centralizzato contenente questa (e qualsiasi altra) funzione personalizzata, quindi eseguire semplicemente la forceHTTPS()funzione.

Soluzione HTACCESS / mod_rewrite

Non ho implementato personalmente questo tipo di soluzione (ho teso ad usare la soluzione PHP, come quella sopra, per la sua semplicità), ma quanto segue potrebbe essere, almeno, un buon inizio.

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]

per curiosità, perché il RewriteCond %{REQUEST_METHOD} !^POST$?
depoulo

12
Perché i parametri POST non vengono conservati su un reindirizzamento. È possibile omettere quella riga se si desidera assicurarsi che tutti gli invii POST siano protetti (eventuali invii POST non garantiti verranno ignorati).
Luke Stevenson,

@Lucanos - Come scrivere un RewriteCond che non forza un reindirizzamento a http o https quando POST? Il mio .htaccess forza HTTPS su determinate pagine specifiche, quindi forza HTTP su tutto il resto. Tuttavia, nelle pagine HTTPS, ci sono moduli che inviano alla mia radice web. Il modulo specifica l'URL dell'azione come HTTPS. Tuttavia, poiché la radice Web non è una di quelle pagine specificate per forzare HTTPS, il mio .htaccess forza quindi un reindirizzamento, il che significa che le variabili POST vanno perse. Come posso impedire i reindirizzamenti su POST?
StackOverflowNewbie

1
@StackOverflowNewbie: la linea RewriteCond %{REQUEST_METHOD} !^POST$dovrebbe impedire che gli invii POST siano interessati da questi reindirizzamenti.
Luke Stevenson,

Mi piace questa versione di PHP. È molto meglio in quanto considera un POST e gestisce meglio se le intestazioni sono già state inviate.
TheStoryCoder

10

Soluzione basata su riscrittura mod:

L'uso del seguente codice in htaccess inoltra automaticamente tutte le richieste http a https.

RewriteEngine on

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

Questo reindirizzerà le tue richieste http non www e www alla versione www di https.

Un'altra soluzione (Apache 2.4 *)

RewriteEngine on

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

Questo non funziona con le versioni precedenti di apache poiché la variabile% {REQUEST_SCHEME} è stata aggiunta a mod-rewrite dal 2.4.


9

Vorrei solo sottolineare che Apache ha le peggiori regole di ereditarietà quando si utilizzano più file .htaccess in profondità di directory. Due insidie ​​chiave:

  • Solo le regole contenute nel file .htaccess più profondo verranno eseguite per impostazione predefinita. È necessario specificare la RewriteOptions InheritDownBeforedirettiva (o simile) per modificarla. (vedi domanda)
  • Il modello viene applicato al percorso del file relativo alla sottodirectory e non alla directory superiore contenente il file .htaccess con la regola specificata. (vedi discussione)

Ciò significa che la soluzione globale suggerita sul Apache Wiki fa non funziona se si utilizza qualsiasi altro file .htaccess nelle sottodirectory. Ho scritto una versione modificata che fa:

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/

0

Semplice e facile, basta aggiungere quanto segue

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Questo è praticamente ciò che le persone su Internet ti dicono di fare per forzare https. Tuttavia, ogni volta che lo faccio, il mio intero sito Web diventa VIETATO o non hai il permesso di visualizzarlo. qualcosa del genere ... Cosa sto facendo di sbagliato? Voglio solo sapere se hai qualche idea prima di pubblicare una domanda al riguardo.
Giovedì

Ho avuto un problema simile e ho dovuto applicare le regole al file https.conf. Vedi la mia risposta qui sotto.
Risteard

-1

Questo codice funziona per me

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

-1

Semplice:

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

sostituisci il tuo URL con example.com


NO! L'URL del sito deve essere dinamico.
Amir Savand,

-1

solo per forzare SSL con .htaccess di Apache che puoi usare

SSLOptions +StrictRequire
SSLRequireSSL

per il reindirizzamento la risposta sopra è corretta


-1

prova questo codice, funzionerà con tutte le versioni di URL come

  • 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]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.