问题
Say, I have a website mywebsite.com
, hosted using Apache Httpd. Now what I want is that whenever any user types mywebsite.com
or www.mywebsite.com
and if the browser supports SNI then it should redirect to https://www.mywebsite.com
else redirect to http://www.mywebsite.com
.
So, what is the most efficient way to achieve it ?
回答1:
The below code should work
Options -Indexes +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^mywebsite.com$
RewriteCond %{HTTPS} (on|off)
RewriteRule ^(.*)$ http://www.mywebsite.com/$1 [R=302,L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule ^(.*)$ https://www.mywebsite.com/$1 [R=302,L]
Here we are neglecting most of the browsers which does not support SNI and hence for them only the http version would be loaded.
回答2:
A better solution would be
#Test if new browser and if so redirect to https
#new browser is not MSIE 5-8, not Android 0-3,
#not any symbian and not any blackbery
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !MSIE\ [5-8] [NC]
RewriteCond %{HTTP_USER_AGENT} !Android.*(Mobile)?\ [0-3] [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
This ignores MSIE 5-8 which excludes all IE on XP, plus some on VISTA that would work. But allows XP with chrome, firefox, opera, all of which support SNI on XP. That at least allows XP users to use https. Likewise it assumes all symbian, blackbery don't have sni. And that android 3 does (which tablets do I'm told, phones need 4).
For a different solution you could have
#Could use this to set $_SERVER['SSL_TLS_SNI'] for php
SetEnv SSL_TLS_SNI %{SSL:SSL_TLS_SNI}
This would set $_SERVER['SSL_TLS_SNI'] to either %{SSL:SSL_TLS_SNI} (yeah could be better code), or the domain name. If you know what is the default cert that apache returns and have access to that domain then in the other domains you could get php to do a test https to the default domain and then check $_SERVER['SSL_TLS_SNI'] to test for SNI before going to https.
Note there is no way to avoid an error message if a non-sni browser does https to a site which needs sni. The best you can do is
# Test if SNI will work and if not redirect to too old browser page
RewriteCond %{HTTPS} on
RewriteCond %{SSL:SSL_TLS_SNI} =""
RewriteRule ^ http://www.example.com/too-old-browser [L,R=307]
The user needs to accept the browser error and continue to website, after which he gets redirected to http and the error page.
回答3:
This is what I used based on the answers above.
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=302]
RewriteCond %{HTTP_USER_AGENT} !MSIE\s7
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
RewriteCond %{HTTP_USER_AGENT} !Android.*(Mobile)?\ [0-3] [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
This rewrites to http first and then rewrites to https if useragent is not listed. I dont know if this is bad having two rewrites but I am sure google and other relevant bots prefer indexing https. This way achieves that (I Think :)
My backwards way of doing it but it seems to work. I am sure your better blacklisting browsers and navigating them to HTTP rather than whitelisting browsers as there is way too many to add.
Every site is different and depending on security the above could be an option.
Please let me know your thoughts.
回答4:
You could set up a second server that would only work with SNI and make the page on your first site make an Ajax request to it (possibly with some identifier if needed).
If the client doesn't support SNI, the server will presented with an invalid certificate for the requested host name. Hence, that Ajax request won't work. You could have your initial page react to that failure, as an indication that SNI isn't supported.
Of course, this isn't perfect, but this might be better than having to depend on an explicit list of user agents (depending on the constraints you have). This would be more along the lines of testing client capabilities directly.
来源:https://stackoverflow.com/questions/23978786/what-is-the-most-efficient-code-to-detect-and-redirect-sni-supported-browsers