简体   繁体   中英

Forcing SSL for all but one directory in CodeIgniter with .htaccess

I realize that there's been a lot of questions along these lines but at this point I've read through nearly all of them and I think my situation is unique.

I'm basically trying to use .htaccess to force HTTPS for everything but make it optional for one directory (which is called pirate). I've done things like this before but this time it didn't cooperate. First I started with this code which successfully forces everything to use HTTPS.

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  RewriteCond %{SERVER_PORT} 80
  RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

  RewriteCond $1 !^(blog|images|css|js|robots\.txt|favicon\.ico)
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
  ErrorDocument 404 /index.php
</IfModule>

Then I added the exception (I'm showing just the first rule here):

RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^(/pirate/) [NC]
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

That should do it! All controllers should go to HTTPS:

1) http://www.mysite.com/contact/ -> https://www.mysite.com/contact

Check. My pirate controller should also be able to do HTTPS:

2) https://www.mysite.com/pirate/ -> https://www.mysite.com/pirate/

No change. Perfect! Lastly the pirate controller should be able to do good old HTTP:

3) http://www.mysite.com/pirate/ -> https://www.mysite.com/index.php?/pirate/

That's not right. It still forces HTTPS and it stopped hiding the index.php. So to summarize, I have two conditions and a rule. It seems like if the first condition is true and the second one is false then the rule is applied and then the second rule is applied and THEN the 301 redirect is returned. I know that sounds strange but if it wasn't I wouldn't be asking.

Why is this happening and how do I fix it?

You need to add an additional exclusion for your controller, or add a passthrough at the top. So either:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  RewriteCond %{SERVER_PORT} 80
  RewriteCond %{REQUEST_URI} !^/pirate/ [NC]
  RewriteCond %{REQUEST_URI} !^/index\.php [NC]
  RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

  RewriteCond $1 !^(blog|images|css|js|robots\.txt|favicon\.ico)
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?/$1 [L]
</IfModule>

or

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  RewriteRule ^index\.php$ - [L]

  RewriteCond %{SERVER_PORT} 80
  RewriteCond %{REQUEST_URI} !^/pirate/ [NC]
  RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

  RewriteCond $1 !^(blog|images|css|js|robots\.txt|favicon\.ico)
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?/$1 [L]
</IfModule>

The reason the redirect was happening is that the rewrite engine loops. After the original URI get routed to index.php , the rewrite engine loops again and the redirect rule gets applied and the routed URI gets redirect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM