https redirect for Network Solutions
I am using Network Solutions as a hosting provider with a UNIX hosting package. I need to redirect certain pages to https (login, etc). After going through a lot of testing, I ended up with the following .htaccess entry:
RewriteEngine on
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://[domain_redacted]/$1 [R=301,L]
This r开发者_如何学Cesulted in an infinite redirect loop. After discussions with Network Solutions, they told me I needed to 301 redirect (apparently what I was doing is not a 301 redirect ...), so I then tried the following in .htaccess:
Redirect 301 / https://[domain_redacted]/
This, of course, resulted in an infinite loop, as one would expect. Since none of these methods worked, I put the following php script on my server to test https detection through PHP:
<?php
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
echo 'HTTPS IS ON';
} else {
echo 'HTTPS IS OFF';
}
?>
When requesting this page over both HTTP and HTTPS, the script returns OFF.
So, what other methods exist to detect HTTPS server side in Apache or PHP?
I asked only so I could answer the question, mostly because I couldn't find a solution anywhere.
Background: The way Network Solutions handles their shared hosting systems, you don't actually connect to a server, you connect to a proxy server (this makes sense). When you perform an https redirect like:
RewriteEngine on
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://[domain_redacted]/$1 [R=301,L]
You do, in fact, redirect the page to HTTPS. However, you are performing your HTTPS transaction with the proxy server, not your hosting server. The proxy server translates your HTTPS connection with it to HTTP over port 80. When attempting to detect this with .htaccess, the server doesn't see HTTPS because the connection between your hosting server and the proxy will always be HTTP on port 80. Because PHP pulls the HTTPS variable from Apache, it will have the identical outcome to detecting HTTP through .htaccess.
Therefore, unless I am mistaken, it is impossible to perform a self-referencing HTTP to HTTPS redirect when on shared hosting from Network Solutions. The request must somehow change (either through a change in the URI or the Query String) in order for the server to detect the change. This, of course, is completely spoofable (e.g. no matter how you change the URI/Query String, one can simply type it into the browser as http and the server would never know), negating the whole point of HTTPS.
I tried checking if %{HTTP_REFERER} referenced itself, but it did not using mod_rewrite.
The only workaround I can come up with is through client-side detection with javascript. This has its own pitfalls (NoScript, etc). But I cannot come up with another solution to the problem. The following code will approximate a 301 redirect.
if(document.URL.match(/^https/i) == null) {
var NetworkSolutionsSucks = document.createElement('meta');
with (NetworkSolutionsSucks) {
httpEquiv = 'refresh';
content = '0;url=' + document.URL.replace(/^http/i,'https');
}
document.head.appendChild(NetworkSolutionsSucks);
var msg = document.createElement('div');
with (msg) {
innerHTML = 'This page requires a secure connection, you are being redirected.<br><br>';
innerHTML += 'If the page does not load, please click <a href="' + document.URL.replace(/^http/i,'https') + '">Here</a>';
}
var newBody = document.createElement('body');
newBody.appendChild(msg);
document.replaceChild(newBody, document.body);
}
Include the above script in the header of any document you want to force HTTPS (forcing HTTP is left as an exercise for the reader - it's a simpler script, not requiring the manual redirect on some failure). You should use a noscript tag with this (obviously); you can use the following:
<noscript id="networkSolutionsHTTPSRedirect">This site requires javascript in order to operate properly. Please enable javascript and refresh this page.</noscript>
<style type="text/css">#networkSolutionsHTTPSRedirect{position: fixed; height: 100%; width: 100%; top: 0; left: 0; z-index: 500;}</style>
<script type="text/javascript">
<!--
document.getElementById("networkSolutionsHTTPSRedirect").style.visibility = "hidden";
document.getElementById("networkSolutionsHTTPSRedirect").style.display = "none";
-->
</script>
EDIT: I figured out a way to do this server side:
You can try to force the entire site to HTTPS if you do the following on every page:
<?php
if((!isset($_ENV['HTTP_REFERER']) || preg_match('/^http[s]{0,1}:\/\/' . $_ENV['SERVER_NAME'] . '/i',$_ENV['HTTP_REFERER']) == 0) && !isset($_ENV[HTTP_X_HTTPS_REDIRECT])) {
header('X-HTTPS-REDIRECT: true\n');
header('Location:' . preg_replace('/^http/','https', $_ENV['SCRIPT_URI']));
}
?>
This should introduce a redirect to all requests that don't have HTTP_REFERER set to your site and do not carry the custom X-HTTPS-REDIRECT header that you inject. This doesn't really detect HTTPS, but performs a reasonable facsimile (at least its server side).
You could, of course, modify the regex so that only certain sites need to be HTTPS by matching the REFERER to the portion of your domain that you want secured and then negate the test to force HTTP.
I have Network Solutions as my provider as well. This last attempt at scripting with PHP also did not work, resulting in an infinite loop.
Network Solutions offers the following code as the best redirect available from http:// to https:// in Javascript, saying that there is no way to do it server side.
<script language="javascript">
if (document.location.protocol != "https:")
{
document.location.href = "https://subdomain.yourdomain.com" + document.location.pathname;
};
</script>
Their information on the subject can be found here. http://www.networksolutions.com/support/ssl-redirects/
Use the following to force only certain pages to https. In your section to force http, just include the sections/pages that force https in a negated format.
Something like this, perhaps: (.htaccess)
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# Force https for mode= login, account or register, and the /admin directory:
RewriteCond %{HTTPS} !=on
RewriteCond %{QUERY_STRING} mode=(login|account|register) [OR]
RewriteCond %{REQUEST_URI} admin/
RewriteRule (.+) https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
# force http for all NON login, account, register (query string)
# and anything else outside the /admin directory
RewriteCond %{HTTPS} on
RewriteCond %{QUERY_STRING} !mode=(login|account|register)
RewriteCond %{REQUEST_URI} !admin/
RewriteRule (.+) http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
The PHP variable:
$_ENV['SCRIPT_URI']
will return the full request string, including protocol.
<?php
if(preg_match('/^https/i',$_ENV['SCRIPT_URI']) == 0) {
header('Location: ' . preg_replace('/^http/i','https', $_ENV['SCRIPT_URI']));
}
?>
This is the ONLY Clean way to Redirect with Networksolutions. Took me hours of testing. Works best for SEO. Network Solutions is a challenging Hosting platform.
This will work .htaccess all you replace is changeexample.com with your domain. Easy.
## Base Redirects ##
# Turn on Rewrite Engine
RewriteEngine On
# Remove trailing slash from non-filepath urls
RewriteCond %{REQUEST_URI} /(.+)/$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ https://changeexample.com/%1 [R=301,L]
# Include trailing slash on directory
RewriteCond %{REQUEST_URI} !(.+)/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+)$ https://changeexample.com/$1/ [R=301,L]
# Force HTTPS and remove WWW
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [OR,NC]
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://changeexample.com/$1 [R=301,L]
Best of Luck! This is current as of 05/14/2021
精彩评论