WebDeveloper.com �: Where Web Developers and Designers Learn How to Build Web Sites, Program in Java and JavaScript, and More!   
Web Developer Resource Directory WebDev Jobs
Animated GIFs
CSS Properties
HTML 4.01 Tags
Site Management
WD Forums

    Web Video
    Expression Web



    Forum, Blog, Wiki & CMS

 Site Management
    Domain Names
    Search Engines
    Website Reviews

 Web Development
  Business Issues

    Business Matters

    The Coffee Lounge
    Computer Issues

.htaccess Magic Impress Your Friends

by J.M. Ivler

The .htaccess file provides the ability for information protection on the HTTP server. It can also provide you with a bit more control. Most Web servers have configuration controls and commands that permit fine granularity of access control to pages and data that reside on the server. This can generally be done from either the system-wide configuration files or from the .htaccess files. The .htaccess files have the same directory limitation capabilities that are available from the configuration files, but are set up in a way that permits direct access to configuration by the person maintaining the directory, and doesn't require server restart to upgrade or modify the security of the directory. Experts in the engineering profession refer to this type of file as empowering, since control for security of the data within the sphere of control for that directory belongs to the person who accepts responsibility for that directory.


The .htaccess file provides the ability for information protection on the HTTP server. That means that access control via the HTTP protocols are controlled on all the page information and data within a directory. This protection is generally done by a user name and a password schema. What does that mean for you? It means that you can provide limited access to the pages under a directory structure by allowing only certain people and certain action within the directory structure. This requires the use of two files. The first is the .htaccess file that lives in the directory where the access will be granted or limited. The second is the .htpasswd file which can live in any location within the server. The full Unix pathname is required to define the file and its location. Here is an example of the contents of an .htaccess file.

AuthUserFile /secdir/.htpasswd
AuthGroupFile /dev/null
AuthName ByPassword
AuthType Basic

require user zippy

As you can see, the file has some interesting capabilities. Using this file, we can allow or disallow access from domains, from individual groups of users, or from an individual user. Let's take a closer look at how we would accomplish each of these. Allowing and Disallowing Domains In this case, we have no need for the password and the group files. In addition, we will be using the basic method. So our .htaccess file would start with:

AuthUserFile /dev/null
AuthGroupFile /dev/null
AuthName AllowLocalAccess
AuthType Basic

Note that we have set the password and the group files to /dev/null. This has been done to ensure that there is no chance of picking up some stray or unnecessary file.

order deny,allow
deny from all
allow from .localdomain.com

Here we have effectively limited access to the directory by stating that the user can only do GETs and POSTs if we permit that from their domain. The first thing we do is deny everyone access to GET and POST; this is the default state. We use the keyword all to make the default cover anyone we don't wish to have access. Then, we use the allow directive for domains to which we want to allow access. Note that we prefix the domain with a period character. That means that any subdomain within that domain can access the directory. The allow and deny directives are permitted to have multiple hosts on the allow and deny lines. The following line in the file above would have allowed people from .localdomain.com and .otherlocal.com to access the private directory.

allow from .localdomain.com .otherlocal.com

You can further enhance the limitations by using the require directive, as in these examples:

require user ivler
require group authors
require valid-user husain

The require user directive states that, even if a person is permitted by the allow directive, their user name still must be in the permitted users file (.htpasswd). The require user form of the directive means that the person's user name must be in the group file if the keyword is group. And, if the keyword is valid-user, the user must enter their name and password to validate that they are permitted into the directory. By default, the user must satisfy all the given directives. The file can also contain the directive satisfy. The satisfy directive is used to allow any (a keyword) require directive to be satisfied, and then all directives will be satisfied. Again, the default is the keyword all, so it is not required. This is used to open the security up a tad, rather than keeping it tightly closed.

Allowing and Disallowing Users

How do we permit or deny access to the directory by user name? This was touched on a bit above when we used the require directive. To allow or to deny users, you must have a file that is used to hold user names and passwords. This file is not the same as that used to store account passwords (/etc/passwd). This means that you don't have to create accounts for users to provide security on Web access to a directory. The path to the file that contains the user names and passwords is defined in the AuthUserFile directive. The path name must be the full Unix pathname to the file. We could do the following if we were protecting a directory called /usr/name/inprogress/:

mkdir /usr/name/inprogress/.data
./htpasswd -c /usr/name/inprogress/.data/.htpasswd userid

The first command will make a hidden directory; the second will run a program called htpasswd (the code, htpasswd.c, is provided in an NCSA HTTPd distribution). That program will create (via the -c option) the file /usr/name/inprogress/.data/.htpasswd and load the user name userid to the file. It will then prompt a password from that user, and a confirmation. That will look like:

./htpasswd -c /usr/name/inprogress/.data/.htpasswd userid
Adding password for userid.
New password:
Re-type new password:

To add additional user names and passwords, you can simply use the htpasswd program without the -c option. This process be automated and run from an interactive Web page. To do this, the CGI script will need to do two things. First, it will have to be able to open and write to the .htaccess file if the person is adding a new entry (name). Then, it will have to be able to run the htpasswd program against the correct .htpasswd file (for additions or for updates). Neither of these is impossible and can be easily performed in Tcl, Perl or even in shell language. Some of the potential problems to look out for are disallowing duplicate user names, making sure that users are aware that the password information is passed in the open and should not match any other password information that they have on-line and, most importantly, not allowing for one user to change the password of another.

Allowing and Disallowing Groups Grouping is a concept that allows a number of users to be established as part of a group. This allows a directory to be secured with a group access which lowers the amount of overhead for the person maintaining access. Let's use the example above, where we want to add a new person to the area. There are two ways this can be done. The first, as outlined above, required that the .htaccess file be opened up and then the user added to that file. Then we had to create the user entry in the .htpasswd file.

Actually, you don't want to be opening, closing, writing and rewriting the .htaccess file. Sure, it can be done, but we can drive cars off cliffs and we don't do that just because it can be done. If there is an easier route, why not take it? That easier route is the group access file. In this case, we provide group access to the directory by changing the .htaccess file as follows:

AuthUserFile /pathto/passwdfile/.htpasswd
AuthGroupFile /pathto/groupfile/.htgroup
AuthName grouptest
AuthType Basic

require group the-group

In the file .htgroup, you would have a record that looked like:

the-group: user1 user2 user3 user4

where user1,user2, user3, and user4 were users who had entries in the .htpasswd file. Now, imagine a system where each month you add a new month-group to the .htaccess file in the require line. Then, if a user wants to be added, they could be added to the latest month-group in the .htgroup file and have an entry added in the .htpasswd file. Using this method, we are not having to access and update the .htaccess file at all, and it provides a clean and clear method of adding new people to the access list.

Also, using month-groups like the example method keeps the groups nicely compacted into a scheme that can be used to require people to re-access themselves to the system if you so choose. Another common grouping method is by first character and, since both Tcl and Perl have strong sort capabilities, this is also fairly easy to implement. Intranets and Internet: Some Differences and Considerations One of the key aspects of intranets deals with security. On intranets, there are usually documents and information that you don't want to share with the outside world. For instance, it wouldn't be very acceptable if someone from the outside world obtained access to your intranet white pages program, especially if that someone was a competitor, or worse yet, a headhunter.

To ensure that Internets and intranets don't co-mingle, it is important to provide unique platforms for each. If that cannot be done, try some of the following ideas.

  1. Place the two servers onto different ports. The default server port is 80; some common ones besides 80 are 8080, 8088 and 8008 (obviously created by Intel fans-Ed.). If you place your intranet server on any port over 1024, such as port 3100 (the suite number of the floor you are on) or 6200 (the last four digits of a phone number) or even an address like 62030 (as in 62030 Westbrook Lane), it is still a legitimate location for the server and it's just very well hidden from access. The key to using a secondary port for the intranet server is to make it memorable to the inner office, but make it harder for someone else to understand.
  2. Use the controls, as explained before in the .htaccess file, to limit access to the intranet server from the access.conf file. While we don't have room to discuss the access.conf file in this article, one of the many things that it permits is control over what users are permitted to access what directories and what users are not. These same levels of control can be leveraged using .htaccess files at the directory level. If you have a proxy server providing access to the external Web, you must ensure that the server doesn't state that access is coming in from the internal domain. You should arrange for the proxy server to be on a separate subnet within the domain and use IP filtering. It is possible to spoof IPs and this could lead to a possible vulnerability.
  3. Use an .htaccess or access.conf to control access to the cgi-bin. In this way, an intruder could get to static areas, but all activities that require access to the databases or to the CGI programs that access internal databases would be limited.
  4. In much the same way, you could use multiple cgi-bin areas to control who has access to what cgi-bin. In that case the standard cgi-bin area would be open, but you would use .htaccess and access.conf to limit the ability of a person to access the special cgi-bin areas. Directory Listings If your system is called companya.com and there was a request to your system for an HTTP service that looked like http://www.companya.com/, the system will return a file. The file that this returns is called the default file. When the server sees the URL above, the server checks to see what the default file is supposed to be, and it will return that file to the user.
In most systems the default file is called index.html. This file name can be changed in the configuration file. It also can be a list of file names, and it will return the first name on the list. This allows the default file to be a Server Side Include file (index.shtml) or a series of possible files {index.shtml index.html main.html README badlocation.html}. In this series it would start looking to return the first file in the series, and would continue until it hit the last file. If no default file is found, it will then try to index the directory if permitted. This is where things get scary, security-wise. In some cases it might be useful to allow someone to get a directory listing. If you are using the directory to allow people to access it like an FTP archive, then it's nice to let the system take over the listing tasks.

What about having listing on and not having a default file in the directory, like an image library? Do you really want your image library to become a place where people from all over the net can drop by and take images? As we have said, a directory listing can be a very useful tool (it is useful when you are doing development and want to be able to just jump around the directory loading files), but it is also something that is open to potential security abuses. The easiest way to ensure that the directory listing services are not abused is to make sure the last filename in your default list is something like badlocation.html. Then, make sure that every directory has a file in it called badlocation.html that links to a single file. This file should indicate to the user that he or she has come to a location that they could not have reached by following the links on the site. (They should be aware that the owner of the site would prefer that they follow the links that you provide.)

HTML5 Development Center

Recent Articles