Is there a way to hide the fact that I'm using PHP from my users? I wanted to do this for two reasons:
1) So the links in the address bar look cleaner (like here on stackoverflow)
2) To prevent potential hackers of knowing immediately what to look for
Is point 2 even realistic or will a hacker know what I'm using anyway? I'm using nginx with php5-fpm.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
http://eisabainyo.net/weblog/2007/08/19/removing-file-extension-via-htaccess/
In addition to the mod_rewrite changes, also set expose_php to false: http://www.php.net/manual/en/ini.core.php#ini.expose-php
The above (or perhaps below) answers give info on the technical side, let me answer the moral side:
Don't do it. Point 2 is completely invalid, if someone wants to do harm, this won't stop it. Proper security checks however will. Point 1 is meagerly valid, no one types links anymore these days.
The best way to keep your PHP hidden from public access is to structure your folders accordingly. Best practice is to keep your library and application files at least one level up from the public folder, like:
/application
// application files
/library
// library and vendor files
/public (aka public_html, htdocs etc)
index.php
.htaccess
/css
/images
/js
Use htaccess and mod_rewrite to route requests to the index.php file, which will then dispatch the request to the application.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php
This way, you only have a single php file publicly accessible, which merely includes other files not available via any url
1) So the links in the address bar look cleaner (like here on stackoverflow)
mmm. OK
2) To prevent potential hackers of knowing immediately what to look for
Security by obscurity. Trust me, that's not going to slow them down much.
A very valid reason for doing this, however, is so that your website is not tie to a particular development language.
I see several people have already mentioned mod_rewrite. It's one solution - but it's a very complex tool to master. Also, be very careful about embedding CGI variables in the path of the URL - you can quickly break stuff.
A simple solution would be to implement every entry-point php script (i.e. anything with is not an include/require file) as 'index.php' and reference it by it's directory.
Alternatively pick your own file extension and replace the references to .php in the config with your extension.
Related
I'm new in php and trying to build my website.
I have created folder structure on my server listed below.
development (folder)
admin (folder)
.htaccess ( copied from internet)
index.html (file with coming soon banner)
I want to set my .htaccess file to load index.html file by default when users open (abcd.com).
And subfolders would access with hitting the url like abcd.com/admin or abcd.com/developement.
But I did some stupid changes in .htaccess file so it redirect the users to my admin login page which i don't want them to see. ;(
Thanks in Advance.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?abcd.com$
RewriteCond %{REQUEST_URI} !^/admin/web/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /admin/web/$1
RewriteCond %{HTTP_HOST} ^(www.)?abcd.com$
RewriteRule ^(/)?$ /admin/web/index.php [L]
It is a bit unclear why you actually ask this question...
As a web developer you surely should be able to find your way around the rewriting options the apache http server offers by looking into the documentation. But even if not: as #AmanjotKaur pointed out the default behavior of that http server is to serve the index.html file if present. If that is not the case then you should take a look at the DirectoryIndex directive offered by mod_dir... Also it should be easy to simply roll back to an older version of that dynamic configuration file you used (".htaccess"), if you are using a revision control system for your development as you certainly should. Or by using a simple backup which you hopefully have ...
A general hint here is to simplify the situation: instead of trying to implement rules to direct incoming requests simply separate the contents. Your "production site" (which I understand is not usable yet) should not host any content, but just that placeholder you already have. Development should not be done on the same site! Use a separate http server for that or at least a separate host name inside the same http server. That is much easier and offers much more reliable protection.
Anyway, there are situations where one indeed wants to redirect all incoming requests to some specific document or router script, with a few explicit exceptions. This might be what you are looking for here. Since your question is a bit vague in that (your question mentions the path /admin, but your rules implement the path /admin/web/...) we can only give you a starting point. You will have to make your way from there. For which you undoubtedly need to take a look into the documentation of the apache http server's mod_rewrite which you want to use on that dynamic configuration file.
Here is something whici I assume implements something along the lines of what you are looking for. You certainly need to adapt it to your needs, though. You'd need to revise your question and be much more precise in what you actually want if you need further help with that. There is an edit button below your question. Use it ...
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/index\.html$
RewriteCond %{REQUEST_URI} !^/admin/
RewriteCond %{REQUEST_URI} !^/development/
RewriteRule ^ /index.html [R=301]
RewriteCond %{REQUEST_URI} !^/admin/web/
RewriteRule ^/?admin/(.*)$ /admin/web/$1 [END]
RewriteCond %{REQUEST_URI} !^/development/web/
RewriteRule ^/?development/(.*)$ /development/web/$1 [END]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
This implementation will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).
After many hours messing with .htaccess I've arrived to the conclusion of sending any request to a single PHP script that would handle:
Generation of html (whatever the way, includes or dynamic)
301 Redirections with a lot more flexibility in the logic (for a dumb .htaccess-eer)
404 errors finally if the request makes no sense.
leaving in .htaccess the minimal functionality.
After some tests it seems quite feasible and from my point of view more preferable. So much that I wonder what's wrong or can go wrong with this approach?
Server performance?
In terms of SEO I don't see any issue as the procedure would be "transparent" to the bots.
The redirector.php would expect a query string consisting on the actual request.
What would be the .htaccess code to send everything there?
I prefere to move all your php files in a other directory and put only 1 php file in your htdocs path, which handle all requests. Other files, which you want to pass without php, you can place in that folder too with this htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php/$0 [L]
Existing Files (JPGs,JS or what ever) are still reachable without PHP. Thats the most flexible way to realize it.
Example:
- /scripts/ # Your PHP Files
- /htdocs/index.php # HTTP reachable Path
- /htdocs/images/test.jpg # reachable without PHP
- /private_files/images/test.jpg # only reachable over a PHP script
You can use this code to redirect all requests to one file:
RewriteEngine on
RewriteRule ^.*?(\?.*)?$ myfile.php$1
Note that all requests (including stylesheets, images, ...) will be redirected as well. There are of course other possibilities (rules), but this is the one I am using and it will keep the query string correct. If you don't need it you can use
RewriteEngine on
RewriteRule ^.*?$ myfile.php
This is a common technique as the bots and even users only see their requested URL and not how it is handled internally. Server performance is not a problem at all.
Because you redirect all URLs to one php file there is no 404 page anymore, because it gets cached by your .php file. So make sure you handle invalid URLs correctly.
I realize this question has been beaten to death by a lot of people asking it, but most of the answers appear to be for a very specific case that only suits their needs, and so far I have not found a suitable solution (at least, as far as i can see).
My problem is that I am trying to make my website redirect URL parameters from an ID to an actual string.
For example:
www.example.com/?category=1
would display as:
www.example.com/software
while
www.example.com/?category=2
would be displayed as:
www.example.com/software/desktop
From what I've read up, I'm supposed to be looking into an apache rewritemap, and this is where my confusion comes in. I'd really rather not have to load from a flat txt file, as I'd like to make this as dynamic as possible, and I have read that I can make it read from a php file and read it from a MySQL database, which is what I'd like.
The problem with that is that I'm really not too sure what the proper way is of achieving this. The RewriteMap document only somewhat covers flat .txt files, and not achieving it with MySQL.
So basically what I'm asking is if someone can explain how to achieve what I'm looking for, or at least point me in the right direction. Most of the threads I've found so far have sadly not been too helpful as of yet, but it's possible I might have passed by useful ones.
If it helps, right now, my MySQL data is formatted in an inherited structure like so:
ID | Title | Link | Parent
1 | Software | /Software/ | NULL
2 | Desktop Software | /Software/Desktop/ | 1
2 | Mobile Software | /Software/Mobile/ | 2
PS:
I should add that most solutions I've found give this as the example:
RewriteMap examplemap prg:/path/to/file.php
RewriteRule (.*) ${examplemap:$1}
Yet it never gives information as to what is in that file.php, and how it queries and returns the value.
EDIT
I should mention that I am on a shared hosting server, not my own private one, and so I may not have access to all possible options
EDIT 2
Just for the sake of clarity:
What I'm trying to do is make it so that a user who accesses 'example.com/software' would be treated as though they are on 'example.com/?category=1'; basically prettying the link and making it more readable. The only thing is, I'm trying to read it from a database
If you don't have access to the server or vhost config, you can't use RewriteMap anyways. The map itself needs to be defined in either the server or vhost config, not in an htaccess file. But apache 2.4 has an option of using mod_dbd to use an SQL query to define a rewrite map.
If you need to access MySQL, you're probably better off doing all of this in PHP instead of using mod_rewrite. You'd use mod_rewrite to route to your php file, which would then redirect. Maybe something like this?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /file.php?link=$1 [L]
So when someone requests http://example.com/Software/Mobile/, the request gets rewritten to: /file.php?link=Software/Mobile/, and your file.php script would do the lookup.
Or if you actually mean the other way around:
RewriteCond %{QUERY_STRING} category=([0-9]+)
RewriteRule ^$ /file.php?ID=%1 [L]
So when someone requests http://example.com/?category=2, the request gets rewritten to: /file.php?ID=2 and the php script does the lookup.
My suggestion would be to look at utilizing a front controller pattern. I think that once you start getting into user friendly URL's or the concept of "routes", that the front controller can really simply things since you no longer have to worry about mapping specific URL's to specific controllers at the web server level.
If you have Apache mod_dir enabled (chances are you do), you could do something like this in your Apache config or .htaccess:
FallbackResource /index.php
This simple directive will direct any requests that would otherwise cause a 404 error to be directed to a front controller at /index.php.
This can also be done via mod_rewrite like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L,QSA]
In the front controller, you could evaluate the URI and route the request to whatever logic need to handle the request. You could do this via lookup of routes from a database or a hard-coded array of routes or whatever. (I would suggest however that, if using a database, you have a cached version of the routes available for quick access).
There are a number of different PHP route controllers available such that you don't need to reinvent the wheel (most every modern framework has some sort of routing concept).
I currently run a site with 750 pages of .html webpages (yeah I know it was a stupid idea, but I'm a novice). I'm looking to move these to php. I don't really want to set up 750 individual 301 redirects and rewrite each page to .php
I've heard that I can use htaccess to this. Anyone know how?
A few additional questions -
Can I permanently redirect these links from html to php without losing my search engine rankings and
if I want to add php to each of the files (i.e. a php file menu (using the include command) to make the links quicker to update will this work? Because won't they still be html files?
Sorry for the stupid questions, but I'm still learning.
Congratulations on a 750 page site - you must have put some work into that.
To collect your current list of pages use a tool called xenu to create an export into excel. You can then easily change the name the files to PHP in column b and create a .htaccees file.
However why would you want 750 php files? If you have lots of data pages, make it one page and suck in the HTML main content and reference one page. If you have a page called warehouse-depot-22-row-44.html then change that to show-warehouse-row.php?depot=22&row=44 and return that content only. This will significantly reduce your number of pages and to start using databases to render the content.
For redirecting you could use the Apache Module mod_rewrite: https://httpd.apache.org/docs/current/mod/mod_rewrite.html
You can use url rewriting to match a specific file name request with a regular expression and then decide where to redirect if matched
RewriteRule ^myname/?$ myname.php [NC,L]
http://www.addedbytes.com/articles/for-beginners/url-rewriting-for-beginners/
Depends on the structure you have.
You want the user to access them in their natural location?
/public_html/folder1/file.php
user would access like
mydomain.com/folder1/file
or you want to map them differently?
Personally I think I would use a rewrite rule to map all requests to my /public_html/index.php and would map the requests from there using php (using include for instance). This gives great flexibility, plus you have a single point of entry for your application which is very beneficial since you can easily maintain control of the application flow.
The .htaccess would look like this
#
# Redirect all to index.php
#
RewriteEngine On
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_URI} !^/index\.php
# RewriteCond %{REQUEST_URI} (/[^.]*|\.(php|html?))$ [NC]
RewriteCond %{REQUEST_URI} (/[^.]*|\.)$ [NC]
RewriteRule .* index.php [L]
of course I place all my not directly accessible files (everything except index and css, js, images, etc) to a folder outside the public_html to ensure no user can ever access them directly ;)
I've had a similar (yet much much smaller) site that went through the same thing.
I have this in my .htaccess:
RewriteEngine On
RewriteRule ^(.*)\.html$ $1.php [L]
This will help redirect any visitors to your .html addresses to your .php addresses.
You hopefully have an IDE (I recommend Aptana), and you can use some of the find/change functions project-wide, and hopefully with some time and patience get your internal links from .html to .php.
But, I caution you a little bit - Perhaps it is time to look into a database based CMS, such as Wordpress or Drupal?
I have a PHP web app located on shared hosting.
My goal is to modify .htaccess file from PHP code when the PHP page is running.
I need that .htaccess to insert a couple of mod_rewrite lines into it.
The problem is that on Windows+Apache I can dynamically modify .htaccess file
but the same code on Linux reports a problem when I try to access this file in any
way (copy or fopen):
"failed to open stream: Permission denied"
I have given .htaccess file 777 permissions - still no result.
WHat prevents me from doing this? How can I develop a workaround?
P.S.
My initial goal was to be able to add a new RewriteRule into .htaccess that maps a
newly added category_id with new category_name.
If it wasn't shared hosting, I would use something like RewriteMap (in main Apache config) and would be able to access the map file.
This is the first real limitation I've been unable to tackle with PHP+Apache, but I hope it's circuventable too.
This seems like an overly-complex solution to just having a general "load category" page that takes the category name from the URL and loads the corresponding ID.
For example, if the URL is:
http://yoursite.com/category/programming
I would remap that to something like:
http://yoursite.com/category.php?name=programming
I want to suggest something else that also works. Instead of writing a rule for every 'special' url, why not use one for all?
I found it a whole lot easier to use what wordpress uses: every url is redirected to the index.
All you have to do is, set up the index file, read in the directory that was loaded (perhaps using $_SERVER['URI_REQUEST']), and deal with it.
add to .htaccess this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Thanks to that chunck you have a system somewhat unlimited at your disposal. If you ever feel like renaming you categrory url, or add another special case, it's already ready!
You only need a small set of rewrite rules. To do what Chad suggests:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/category/.*$ category.php [QSA]
Thus, anytime someone navigates to /category/category_id, the request will be directed to category.php, which will be handed the /category/ URI in $_SERVER['REQUEST_URI'], from which you can easily get the category ID, and you don't need to bother with editing the .htaccess file every time you add a category.
While I agree with the above comments, it can definitely be done. PHP apps like WordPress do exactly this based on changes made on the settings page. It should be as simple as writing the file out however the parent directory NEEDS to have permission for the web server user to write to it.
If it isn't working for you the trick will be making the parent directory either 777 or 775 and having the group set to whatever group Apache runs under (usually "apache" or "www" or something similar)
Adam (commented on your question) is quite correct though, some other security layer on your server might be preventing you from doing this, and this is probably a good indication that you might be approaching the problem the wrong way.
I agree with Chad Birch. In case you can't be dissuaded, though, in your situation I would first be looking for parent directories with locked-down permissions.
FYI, one of the reasons that rewriting the .htaccess is a bad idea is that any requests that come in while the .htaccess is being rewritten will not have any of your redirects applied.