Forzar SSL / https usando .htaccess y mod_rewrite

Respuestas:

438

Para Apache, puede usar mod_sslpara forzar SSL con SSLRequireSSL Directive:

Esta directiva prohíbe el acceso a menos que HTTP sobre SSL (es decir, HTTPS) esté habilitado para la conexión actual. Esto es muy útil dentro del host virtual o directorios habilitados para SSL para defenderse contra errores de configuración que exponen cosas que deberían protegerse. Cuando esta directiva está presente, se rechazan todas las solicitudes que no utilizan SSL.

Sin embargo, esto no redirigirá a https. Para redirigir, intente lo siguiente con mod_rewritesu archivo .htaccess

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

o cualquiera de los diversos enfoques dados en

También puede resolver esto desde PHP en caso de que su proveedor haya deshabilitado .htaccess (lo cual es poco probable ya que lo solicitó, pero de todos modos)

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
fuente
1
Esto es excelente en nuestra situación porque actualmente tenemos una mezcla de tráfico http y https. Para nuestra área de administración, acabamos de ingresar el script .htaccess mientras mantenemos el resto del sitio http.
Michael J. Calkins
1
Cuando uso el método mod_rewrite, me envían a https pero con el error "La página no está redirigiendo correctamente".
Czechnology
11
Seguimiento: si tiene problemas similares, verifique su servidor y las variables HTTP. Si sus usos de servidor proxy, es posible que desee utilizar %{HTTP:X-Forwarded-Proto}o %{HTTP:X-Real-Port}variables para comprobar si SSL está activada.
Czechnology
8
Si experimenta bucles de redireccionamiento en servidores que se ejecutan detrás de servidores proxy ( CloudFlare , Openshift ), consulte esta respuesta para obtener una solución que también funcione para ese caso.
raphinesse
44
@GTodorov - Eliminar el espacio rompió la reescritura para mí. Desde mi conocimiento (limitado) de reescrituras, la sintaxis es RewriteRule <input-pattern> <output-url>. Por lo tanto, el espacio debe estar allí, y el sencillo ^solo dice "coincide con todas las URL de entrada".
Sphinxxx
54

Encontré una mod_rewritesolución que funciona bien para servidores con y sin proxy.

Si está utilizando CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift o cualquier otra solución Cloud / PaaS y está experimentando bucles de redireccionamiento con redireccionamientos HTTPS normales, intente con el siguiente fragmento.

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
fuente
Esto es genial gracias! Pero tal vez es necesario agregar la condición de publicación? RewriteCond% {REQUEST_METHOD}! ^ POST $
Aleksej
@Aleksej Cierto, esto interrumpe las solicitudes POST sin cifrar. Pero creo que esto es algo bueno. De esta manera, las personas notarán que están haciendo algo mal. Supongo que lo mejor sería redirigirlos a una página que les informe sobre cómo usar adecuadamente su servicio.
raphinesse
@raphinesse ¿Conoces la respuesta a esta pregunta? stackoverflow.com/questions/51951082/…
RRN
36

Solución PHP

Tomando prestado directamente de la respuesta muy completa de Gordon, noto que su pregunta menciona que es específica de la página al forzar conexiones 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>' );
    }
  }
}

Luego, tan cerca de la parte superior de estas páginas que desea forzar a conectarse a través de PHP, puede require()crear un archivo centralizado que contenga esta (y cualquier otra) función personalizada, y luego simplemente ejecutar la forceHTTPS()función.

Solución HTACCESS / mod_rewrite

No he implementado este tipo de solución personalmente (he tendido a usar la solución PHP, como la anterior, por su simplicidad), pero lo siguiente puede ser, al menos, un buen comienzo.

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
fuente
por curiosidad, ¿por qué RewriteCond %{REQUEST_METHOD} !^POST$?
depoulo
12
Porque los parámetros POST no se retienen en una redirección. Puede omitir esa línea si desea asegurarse de que todos los envíos POST sean seguros (se ignorará cualquier envío POST no seguro).
Luke Stevenson
@Lucanos - ¿Cómo escribir un RewriteCond que no fuerce una redirección a http o https cuando POST? Mi .htaccess fuerza HTTPS en ciertas páginas específicas, y luego fuerza HTTP en el resto. Sin embargo, en las páginas HTTPS, hay formularios que se envían a mi raíz web. El formulario especifica la url de acción como HTTPS. Sin embargo, dado que la raíz web no es una de esas páginas que están especificadas para forzar HTTPS, mi .htaccess luego fuerza una redirección, lo que significa que las variables POST se pierden. ¿Cómo evito los redireccionamientos en POST?
StackOverflowNewbie
1
@StackOverflowNewbie: la línea RewriteCond %{REQUEST_METHOD} !^POST$debe evitar que los envíos POST se vean afectados por estas redirecciones.
Luke Stevenson
Me gusta esta versión de PHP. Es mucho mejor ya que considera una POST y se maneja mejor si los encabezados ya se han enviado.
TheStoryCoder
10

Solución basada en reescritura mod:

El uso del siguiente código en htaccess reenvía automáticamente todas las solicitudes http a https.

RewriteEngine on

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

Esto redirigirá sus solicitudes http que no sean www y www a la versión www de https.

Otra solución (Apache 2.4 *)

RewriteEngine on

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

Esto no funciona en versiones inferiores de apache ya que la variable% {REQUEST_SCHEME} se agregó a mod-rewrite desde 2.4.

Starkeen
fuente
9

Solo me gustaría señalar que Apache tiene las peores reglas de herencia cuando se usan múltiples archivos .htaccess en profundidades de directorio. Dos escollos clave:

  • Solo las reglas contenidas en el archivo .htaccess más profundo se realizarán de manera predeterminada. Debe especificar la RewriteOptions InheritDownBeforedirectiva (o similar) para cambiar esto. (ver pregunta)
  • El patrón se aplica a la ruta del archivo relativa al subdirectorio y no al directorio superior que contiene el archivo .htaccess con la regla dada. (ver discusión)

Esto significa que la solución global sugerido en la Wiki Apache hace no funcionan si se utiliza cualquier otro archivo .htaccess en subdirectorios. Escribí una versión modificada que hace:

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
fuente
0

Simple y fácil, solo agregue lo siguiente

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Saurabh Mistry
fuente
Esto es más o menos lo que la gente en Internet te dice que hagas para forzar https. Sin embargo, cada vez que hago eso, todo mi sitio web queda PROHIBIDO o no tienes permiso para verlo. algo así ... ¿Qué estoy haciendo mal? Solo quiero saber si tienes alguna idea antes de publicar una pregunta sobre esto.
Jueves
Tuve un problema similar y tuve que aplicar las reglas al archivo https.conf. Vea mi respuesta a continuación.
Risteard
-1

Este código me funciona

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

Uno simple:

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

reemplace su url con example.com

Sepehr Norouzi
fuente
¡NO! La URL del sitio debe ser dinámica.
Amir Savand
-1

solo por forzar SSL con Apache .htaccess puedes usar

SSLOptions +StrictRequire
SSLRequireSSL

para redirigir la respuesta anterior es correcta

webdesignwien
fuente
-1

pruebe este código, funcionará para todas las versiones de URL como

  • sitio web.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
fuente