强制SSL并处理不支持SNI的浏览器

强制SSL并处理不支持SNI的浏览器,ssl,https,sni,Ssl,Https,Sni,我正在寻找一种方法,将支持SNI的WebBrowser从http重定向到https,并将不支持SNI的WebBrowser从https重定向到http。第二种情况很重要,例如,如果用户收到通过邮件发送的https url,并使用旧浏览器打开该url 我想避免使用用户代理,因为我不想跟踪新的浏览器版本并相应地更新配置文件,例如.htaccess 因此,我使用javascript检测SNI支持并重定向webbrowser。以下代码检查连接是否受SSL保护。如果SSL不安全,它将检查是否支持SNI,并

我正在寻找一种方法,将支持SNI的WebBrowser从http重定向到https,并将不支持SNI的WebBrowser从https重定向到http。第二种情况很重要,例如,如果用户收到通过邮件发送的https url,并使用旧浏览器打开该url

我想避免使用用户代理,因为我不想跟踪新的浏览器版本并相应地更新配置文件,例如.htaccess

因此,我使用javascript检测SNI支持并重定向webbrowser。以下代码检查连接是否受SSL保护。如果SSL不安全,它将检查是否支持SNI,并在支持SNI时重定向浏览器:

<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>
更新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>
更新3: 我们通过PHP使用更可靠的https检测(无重定向循环)


var img=document.createElement('img');
img.src=https://www.example.org/favicon.png';
img.onload=函数(){
var redirect_form=document.forms[“redirect”];
重定向_form.action=“https:”+window.location.href.substring(window.location.protocol.length);
重定向_form.submit();
}
img.style.display='none';
文件.正文.附件(img);
...
未决问题:

  • 如何完全避免使用用户代理?如果不可能,是否缺少任何重要的web爬虫用户代理
  • 使用更新3中描述的方法,“后退”按钮无法正常工作。如果用户从http转发到https,然后单击后退按钮,他将被重定向到http,然后再次从http转发到https。此问题可以通过location.replace()解决,但该方法不支持referer
  • 在下面的示例中,如何使用location.replace()作为引用?示例:google.de->->->->返回按钮单击->(不重定向到google.de!!!)->
  • 如果浏览器不支持javascript,它将被迫使用http
  • 这种方法是否存在未知问题
学分:


  • 由于各种问题,我决定放弃htaccess规则。使用以下代码,支持Javascript和SNI的web浏览器将重定向到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>
    
    不支持SNI的旧web浏览器如果通过https()访问页面,则会重定向到http:

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