.htaccess require SSL for a particular URL - apache

I want to force Apache to use HTTPS for a particular URL in the following form:
https://www.example.com/signup/*
so
if someone goes to any of the following example URLs directly, Apache will forward the URL over to the HTTPS equivalent site.
e.g.
http://www.example.com/signup --> https://www.example.com/signup
http://www.example.com/signup/basic+plan --> https://www.example.com/signup/basic+plan
http://www.example.com/signup/premium --> https://www.example.com/signup/premium
Anyone know how?
Thanks in advance

Thank Murat,
Yours almost worked but figured out how to get it to exactly work.
The following is what works:
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/somefolder/?
RewriteRule ^(.*)$ https://www.domain.com/$1 [R,L]
Notice that I didn't include somefolder in the www.domain.com rewriterule

I think this was what i used:
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/somefolder/?
RewriteRule ^(.*)$ https://www.domain.com/somefolder/$1 [R,L]
(from here)

You can use the Redirect directive:
Redirect 301 /signup https://www.example.com/signup
This will automatically preserve anything following /signup in the URL. Be sure to configure this directive only on your non-SSL site, or it might get into a recursive loop!

You should take a look at mod_rewrite documentation

I used the following to require the checkout section of a website to require SSL:
<Directory "/var/www/html">
RewriteEngine on
Options +FollowSymLinks
Order allow,deny
Allow from all
RewriteCond %{SERVER_PORT} !^443$
RewriteRule \.(gif|jpg|jpeg|jpe|png|css|js)$ - [S=1]
RewriteRule ^checkout(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</Directory>
So for example, hitting http://www.example.com/checkout redirects to https://www.example.com/checkout
The rule will skip file extensions that are typically included within a page so that you don't get mixed content warnings. You should add to this list as necessary.
If you want multiple pages change the RewriteRule to something like:
RewriteRule ^(checkout|login)(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
Of course, the directory should match the actual path on your server. This page may also help with some more information for your specific needs: http://www.whoopis.com/howtos/apache-rewrite.html
I'm using this on a website that runs Plesk 8.6 but that shouldn't matter. This is in my vhost.conf file which is like putting it in your httpd.conf file. I'm not sure if you'd need to adjust anything to use it in a .htaccess file but I doubt it. If adding to a conf file don't forget to restart apache to reload the configuration.
If you are like me and want to use SSL only on particular pages then you also want a rewrite rule that sends you back to regular http for the rest. You can use the following for the reverse effect:
RewriteCond %{SERVER_PORT} ^443$
RewriteRule \.(gif|jpg|jpeg|jpe|png|css|js)$ - [S=1]
RewriteRule !^(checkout|login)(.*)$ http://%{SERVER_NAME}%{REQUEST_URI} [L,R]
If you are using Plesk like I am keep in mind that all non-SSL traffic uses the vhost.conf file but all SSL traffic uses the vhost_ssl.conf file. That means your first rewrite rule to require SSL would go in the vhost.conf file but the second rule to force back to non-SSL will have to go in the vhost_ssl file. If you are using httpd.conf or .htaccess I think you can put them both in the same place.
I've also posted this tutorial on my blog: Apache rewrite rules to force secure/non-secure pages.

You can do this with mod_rewrite -
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/signup https://example.com/signup
RewriteRule ^/signup/(.*)$ https://example.com/signup/$1
Should work, though I haven't tested it.
-- edit --
Correction, I just tried this on one of my servers, and it works fine for me. You may want to doublecheck your mod_rewrite configuration. Also, if you're using .htaccess, you'll want to make sure overrides are allowed for that directory.
As a side note, this assumes your SSL traffic is coming over port 443. If it isn't, you'll need to adjust the rewrite condition accordingly.

.htaccess files are normally placed in a scope with Options -FollowSymLinks, which blocks Rewrite rules. This is often a security rule.
So a more trivial thing is often needed like this one:
<If "%{HTTPS} != 'on'">
Redirect 301 /your/path https://www.example.com/your/path
</If>
This is a small enhancement to the answer of Greg Hewgill.

Related

Apache mod_rewrite for specific folders and paths

I have found dozens of articles online on how to setup mod_rewrites but for the love of God I can't figure out how to PROPERLY force HTTPS on ALL pages and after that force HTTP on certain directories or (already rewritten) pages.
Now this one gets really tricky as I need HTTPS on this directory, except for two cases, such as "/surf" which actually is rewritten from "surf.php", and "promote-([0-9a-zA-Z-]+)$" which is rewritten from "promote.php?user=$1" :
<Directory /home/rotate/public_html/ptp/>
AllowOverride None
Order Deny,Allow
Allow from all
Options +SymLinksIfOwnerMatch
ErrorDocument 404 "<h1>Oops! Couldn't find that page.</h1>"
RewriteEngine On
RewriteRule ^promote-([0-9]+)$ promote.php?user=$1 [QSA,NC,L]
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
</Directory>
I have tried some stuff but which only resulted in some weird redirection loops...
RewriteCond %{HTTPS} on
RewriteRule !^(surf|promote-([0-9]+)$) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
So basically I need to force HTTPS everywhere in /ptp/ except /ptp/surf (which is rewritten from surf.php AND /ptp/promote-123 which is rewritten from promote.php?user=123
Currently I'm using PHP to redirect to HTTP or HTTPS as per my needs but I know that it would be much faster if I could manage to do it via rewrites.
Any pointers, tips, suggestions? Thanks.
UPDATE2: This worked:
RewriteCond %{HTTPS} off
RewriteRule !^(surf|promote(-[0-9]+)?) https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
RewriteRule ^promote-([0-9]+)$ promote.php?user=$1 [NC,L]
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php
However, the resources such as javascript, fonts etc, were being blocked by the browser, unless I specified absolute HTTPS paths. Note that this never happened when redirecting through PHP...
I changed a little bit and it works perfectly
Changes
Remove the Change the RewriteRule to match file to .php to bottom.
Remove the $ sign that is End of the pattern
As Said in the update promote-1111 will redirect to promote.php?user=$1 change the promote-[0-9]+ to promote(-[0-9]+)? otherwise it will override in the second redirection as you redirecting it to promote.php?user=$1
The Code
RewriteCond %{HTTPS} off
RewriteRule !^(surf|promote(-[0-9]+)?) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
The page surf
The Page Index
Never mind the error message shown in this image. Since I tried it from my localhost, it won't have a certificate.
Will work with servers
Your rules aren't in the "update" working because of side effects of using <Directory> context. Each substitution starts processing again.
When you request /promote-123 and rewrite it to put the numbers in the query string, you can't then match the numbers as if they're still in the path. You'll need to match the rewriten path and the numbers with RewriteCond %{QUERY_STRING} (if you care about the numbers)

Using mod_write for cleanurls with Lets Encrypt

I have enabled Let's Encrypt on a server running Apache on Ubuntu 14.04 and used the auto option to re-direct all http requests to https. This is working fine.
However, I now want to use mod_rewrite to use cleanurls on my site - all I need to do is remove the .php extension from all filenames. (e.g. https://example.com/contact routes to https://example.com/contact.php)
I have tried adding the following rewrite rule to the .htaccess file:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
This configuration works fine on my localhost setup (without SSL) but does not work on the instance running Lets Encrypt.
I have tested that the .htaccess is working by adding this rule which works as expected (redirecting all www requests to the root domain)
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
I suspect that there may be some conflict between the Lets Encrypt auto setup option and my mod_rewrite rule but I am stuck as to how to make them both work together.
Any help would be much appreciated.
Disable MultiViews in .htaccess:
Options -MultiViews
MultiViews (part of mod_negotiation) is likely resulting in a conflict. This does something very similar to what you are trying to achieve using mod_rewrite. With MultiViews enabled (possibly enabled in the server config, although the default is disabled), a request for /filename, will result in Apache looking for a file that matches (that would return the appropriate mime-type) by stepping through the files in that directory (essentially trying various extensions where the basename matches).
I have checked what REQUEST_FILENAME is returning - it is the path to the filename (e.g. [REQUEST_FILENAME] => /var/www/sitename/public_html/output.php)
Yeah, that's the problem. MultiViews has already "fixed" the URL (output to output.php) before mod_rewrite has been able to do its thing.

.htaccess URL Rewrite not working

I've never been good at .htaccess, I'm trying to copy and paste some code that worked on another one of my domains and modify it to work here. I will have several rewritten URLs, some static, some dynamic, but I can't even get the simplest of them to work. This one is testable here: http://lindseymotors.com/home
Clearly, index.php is available because if you access http://lindseymotors.com it works.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^.* [NC]
RewriteRule ^home$ index.php
RewriteRule ^home/$ index.php
# When answering, if you could write a statement that would combine
# both of the statements above into one that would be appreciated.
As I said, these same conditions worked on another one my domains because I copied the code right over. I asked my server admin to double check everything on his end and it was fine. Any ideas?
Only thing I can think of is make sure the use of .htaccess is really on. The easiest way you can check since your server admin says it's fine is to put random text at the top of your .htaccess file. If your .htaccess file is being read and .htaccess files are enabled, it should throw a 500 internal server error. If not, then they don't have .htaccess files enabled and need to add AllowOverride All to the Apache config vhost.
Here is your rule combined into one as you noted. You really don't need the RewriteCond, but I will leave since you were using it previously.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^.* [NC]
RewriteRule ^home/?$ index.php [L]

htaccess folder rewrite

I've been reading multiple posts on here about htaccess folder rewriting but none seem to fit my question (properly).
My question is:
I have 2 sub folders on the server, website1 and website2.
When a user goes to www.foo.com I wish the visual url to remain the same but want the server URI to go to /website1/ where it will load the index.php for website1
I then want the same thing only when a user goes to www.bar.com again the url does not change but this time it links to /website2/ where it will load the index.php for the 2nd website.
Would really appreciate some help with this as I'm still learning about rewrites. Examples with explanations would be highly appreciated. Also any advice of best practice (if their is any) would also be appreciated.
KingCrunch is right -- the proper way to setup such environment is to use <VirtualHost> directive in Apache config file.
If, for whatever reason this needs to be dona via rewrite and .htaccess .. then you need mod_rewrite to be enabled and .htaccess files to be allowed to contain rewrite rule (AllowOverride directive).
Here are the rules:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# rule #1
RewriteCond %{HTTP_HOST} =www.foo.com
RewriteCond %{REQUEST_URI} !^/website1/
RewriteRule (.*) /website1/$1 [L]
# rule #2
RewriteCond %{HTTP_HOST} =www.bar.com
RewriteCond %{REQUEST_URI} !^/website2/
RewriteRule (.*) /website2/$1 [L]
This code is to be placed in .htaccess file in root folder. If placed elsewhere (e.g. configuration or virtual host context) some tweaking may be required.
Fist rule is for www.foo.com and second for another domain name. These rules are pretty much the same. We tell Apache to check domain name (via {HTTP_HOST} request variable), and if it matches our domain rewrite (internal redirect) URL into one folder deeper. The second condition is to prevent a rewrite loop (to not to rewrite already rewritten URL). It is necessary as Apache, after executing rewrite, goes to the next rewrite iteration (that is how it works), and this condition is required to stop the loop.
Useful link: http://httpd.apache.org/docs/current/rewrite/
I believe that you need to use only RewriteCond and RewriteRule directives. Take a look 'Virtual User Hosts' at http://httpd.apache.org/docs/1.3/misc/rewriteguide.html.
The logical is the same. (I think.)

Redirecting PDF links from another domain using htaccess

We have two domains, let's call them first.com and second.com
We have a directory in second.com called reports, where all our PDFs are located, but we would like to these same PDFs accessible from first.com as well.
Can we redirect let's say first.com/reports/84839049.pdf to second.com/reports/84839049.pdf using htaccess?
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^domain\.com
RewriteRule (.*) http://domain1.com/$1 [R=301, L]
Yes.
redirect /requested/url http://second.com/result/url
http://httpd.apache.org/docs/1.3/mod/mod_alias.html#redirect
You may want to consider using mod_rewrite though, unless you asked for an .htaccess configuration specifically because you have no access to the server configuration and mod_rewrite is disabled or not loaded.
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
http://webdesign.about.com/od/mod_rewrite/qt/site_redirects.htm
You'll need some grasp of regex for mod_rewrite, but it can make configuration of the redirects a lot faster than having to add a redirect for every file on your site(s).