php to - 使用.htaccess和mod_rewrite強制SSL / https




force redirect (9)

我如何在PHP中使用.htaccess和mod_rewrite頁面強制SSL / https。


Answers

此代碼適用於我

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

基於Mod重寫的解決方案:

在htaccess中使用以下代碼會自動將所有http請求轉發到https。

RewriteEngine on

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

這會將您的非wwwwww http請求重定向到www版本的https。

另一個解決方案(Apache 2.4 *)

RewriteEngine on

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

這對低版本的apache不起作用,因為自從2.4開始,%{REQUEST_SCHEME}變量被添加到mod-rewrite中。


我發現了一個mod_rewrite解決方案,適用於代理和非代理服務器。

如果您正在使用CloudFlare,AWS Elastic Load Balancing,Heroku,OpenShift或任何其他雲/ PaaS解決方案,並且遇到正常HTTPS重定向的重定向循環 ,請嘗試使用以下代碼段。

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]

對於Apache,您可以使用mod_ssl通過SSLRequireSSL Directive強制使用SSL:

該指令禁止訪問,除非為當前連接啟用了HTTP over SSL(即HTTPS)。 這在支持SSL的虛擬主機或目錄內非常方便,可以防範出現應該受保護的配置錯誤。 當此指令存在時,所有拒絕使用SSL的請求都將被拒絕。

雖然這不會做重定向到https。 要重定向,請在.htaccess文件中使用mod_rewrite進行以下操作

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

或者以下給出的各種方法中的任何一種

你也可以在PHP中解決這個問題,以防你的提供者禁用.htaccess(這是不太可能的,因為你問了它,但無論如何)

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

PHP解決方案

我直接從戈登的非常全面的答案中藉用,我注意到你的問題在強制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>' );
    }
  }
}

然後,如果您希望強制通過PHP連接這些頁面的頂部,您可以require()包含此(和其他任何)自定義函數的集中文件,然後只需運行forceHTTPS()函數。

HTACCESS / mod_rewrite解決方案

我個人還沒有實現這種解決方案(我傾向於使用PHP解決方案,就像上面那樣,因為它很簡單),但以下可能至少是一個好的開始。

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]

試試這個代碼,它將適用於所有版本的URLs

  • 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]
    

我只想指出,在跨目錄深度使用多個.htaccess文件時,Apache具有最差的繼承規則。 兩個關鍵陷阱:

  • 只有最深的.htaccess文件中包含的規則將默認執行。 您必須指定RewriteOptions InheritDownBefore指令(或類似)來更改此設置。 (見問題)
  • 該模式應用於相對於子目錄的文件路徑,而不是包含具有給定規則的.htaccess文件的上層目錄。 (見討論)

這意味著如果您在子目錄中使用任何其他.htaccess文件,則Apache Wiki上的建議全局解決方案將不起作用。 我寫了一個修改版本,它可以:

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/

簡單的一個:

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

用example.com替換您的網址


我也在尋找這個解決方案。 我添加了Gumbo的解決方案,它對我很有用。 但我原來的不同。 我的網站/應用程序重寫通過index.php(對於fany urls和../application)重定向所有內容,除了您具體請求的文件。 (就像公共根目錄中的圖像或其他靜態文件一樣)這是我原來的,很久以前我在ZF網站上發現的。

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

以下是Gumbo在整個網站上強制使用SSL的附加規則。 到目前為止對我有用。

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]






php .htaccess mod-rewrite ssl https