2015-01-11 48 views
1

我正在尋找一種方式來重定向web瀏覽器與http支持SNI支持到https和webbrowsers從https到http沒有SNI支持。第二種情況很重要,例如,如果用戶獲得通過郵件發送的https網址並用舊瀏覽器打開該網址。強制SSL和處理瀏覽器沒有SNI支持

我想避免使用用戶代理,因爲我不想跟蹤新的瀏覽器版本並更新配置文件,例如, .htaccess,相應地。

因此,我使用javascript來檢測SNI支持並重定向webbrowser。以下代碼檢查連接是否受SSL保護。如果沒有SSL保護,它會檢查SNI支持和重定向是否支持SNI的瀏覽器:如果用戶訪問該網站的第一次,並使用SSL加密

<head> 
    <script type="text/javascript"> 
    if (window.location.protocol != "https:") { 
     var img=document.createElement('img'); 
     img.src='https://www.example.org/favicon.png'; 
     img.onload = function() { 
      window.location.href = "https:" + window.location.href.substring(window.location.protocol.length); 
     } 
     img.style.display='none'; 
     document.body.appendChild(img); 
    } 
    </script> 
    ... 
</head> 

,他被重定向到HTTP URL以運行JavaScript代碼。否則,舊的瀏覽器會打開安全的網站並顯示錯誤消息。

RewriteCond %{HTTPS} =on 
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example\.org [NC] 
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=302,L] 

更新1: 有重定向循環,因爲JavaScript不提供一個引用。 該解決方案似乎避免循環:

<body> 
    <form style="display:none;" method="get" name="redirect"></form> 
    <script type="text/javascript"> 
     if (window.location.protocol != "https:") { 
     var img=document.createElement('img'); 
     img.src='https://www.example.org/favicon.png'; 
     img.onload = function() { 
      document.redirect.action = "https:" + window.location.href.substring(window.location.protocol.length); 
      document.forms['redirect'].submit(); 
     } 
     img.style.display='none'; 
     document.body.appendChild(img); 
     } 
    </script 
    ... 
</body> 

更新2: 我們希望避免重定向爬蟲。

RewriteCond %{HTTPS} =on 
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example\.org [NC] 
RewriteCond %{HTTP_USER_AGENT} !(googlebot|bingbot|baiduspider) [NC] 
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=302,L] 

更新3: 我們使用通過PHP(無重定向環路)更可靠的HTTPS檢測。

<body> 
<?php if (empty($_SERVER["HTTPS"])) { ?> 
    <form style="display:none;" method="get" name="redirect"> 
     <input type="hidden" name="redirected" value="true" /> 
    </form> 
    <script type="text/javascript"> 
     var img=document.createElement('img'); 
     img.src='https://www.example.org/favicon.png'; 
     img.onload = function() { 
     var redirect_form = document.forms["redirect"]; 
     redirect_form.action = "https:" + window.location.href.substring(window.location.protocol.length); 
     redirect_form.submit(); 
     } 
     img.style.display='none'; 
     document.body.appendChild(img); 
    </script> 
<?php } ?> 
... 
</body> 

開放性問題:

  • 我怎樣才能避免用戶代理完全的使用情況如何?如果不可能,是否有任何重要的網絡爬蟲用戶代理丟失?
  • 使用更新3中描述的方法,後退按鈕無法正常工作。如果用戶從http轉發到https,然後單擊後退按鈕,他將重定向到http,然後再從http再次轉到https。這個問題可以通過location.replace()來解決,但該方法不支持引用。
  • 在以下示例中,如何使用location.replace()和http://www.example.org作爲引用?例如:google.de - >http://www.example.org - >https://www.example.org - >後退按鈕點擊 - >http://www.example.org(無重定向到google.de中!!!) - >https://www.example.org
  • 如果瀏覽器不支持javascript,它被強制使用HTTP。
  • 這種方法有什麼未知的問題嗎?

學分:

回答

1

我決定放棄上述htaccess的規則,由於各種問題。用下面的代碼,支持JavaScript和SNI網絡瀏覽器重定向到SSL安全頁面,而不在用戶代理進行檢查:

<body> 
<?php if (empty($_SERVER["HTTPS"])) { ?> 
    <form style="display:none;" method="get" name="redirect"></form> 
    <script type="text/javascript"> 
     var img=document.createElement('img'); 
     img.src='https://www.example.org/favicon.png'; 
     img.onload = function() { 
     var redirect_form = document.forms["redirect"]; 
     redirect_form.action = "https:" + window.location.href.substring(window.location.protocol.length); 
     redirect_form.submit(); 
     } 
     img.style.display='none'; 
     document.body.appendChild(img); 
    </script> 
<?php } ?> 
... 
</body> 

這些htaccess的規則,消除由以上表格創建尾隨的問號:

RewriteCond %{HTTPS} =on 
RewriteRule ^(.*)$ - [env=proto:https] 
RewriteCond %{HTTPS} !=on 
RewriteRule ^(.*)$ - [env=proto:http] 

RewriteCond %{THE_REQUEST} \?\ HTTP [NC] 
RewriteRule .? %{ENV:proto}://%{HTTP_HOST}%{REQUEST_URI}? [R=301,L] 

不支持SNI舊的Web瀏覽器將被重定向到http如果他們訪問,通過HTTPS頁面(What is the most efficient code to detect and redirect SNI supported browsers?):

SetEnv SSL_TLS_SNI %{SSL:SSL_TLS_SNI} 

RewriteCond %{HTTPS} =on 
RewriteCond %{HTTP_USER_AGENT} MSIE\s6 [NC,OR] 
RewriteCond %{HTTP_USER_AGENT} Windows\sNT\s5 [NC,OR] 
RewriteCond %{HTTP_USER_AGENT} Android.*(Mobile)?\ [0-3] [NC,OR] 
RewriteCond %{HTTP_USER_AGENT} ^(.*.symbian.*) [NC,OR] 
RewriteCond %{HTTP_USER_AGENT} ^(.*.blackberry.*) [NC] 
RewriteCond %{SSL:SSL_TLS_SNI} ="" 
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=307,L]