I moved some static html pages I was hosting from apache into tomcat. (no point in running two servers) This works as expected, but I'm having trouble with the authentication part. In apache the authentication was handled by htaccess. I tried various tutorials on the web about configuring basic authentication in tomcat using WEB-INF/web.xml in tomcat, but I'm not sure this approach applies to static html pages. Can anyone shed some light on using basic authentication for static html in tomcat? Thanks.
J(2)EE has a built-in container-managed authorization system, which, alas, too many people don't use. I say "alas", because more often than not, they invent their own security system and it almost invariably has serious holes in it. However, if you do have the good sense to use J2EE container security, Tomcat supports it to the full extent of its abilities.
Container security is primarily declarative. It consists of 2 primary functions: authentication and authorization.
Authentication is what drives the login process. If a user attempts to access a protected URL and is not logged in, the server (Tomcat) will take over, push the original URL request onto a siding and render the login page that was specified in the application WEB-INF/web.xml file if FORM-based security is specified, or it returns the appropriate status code (401, I think) that causes the login dialog to be displayed by the client if BASIC authentication was specified.
The user supplies credentials in a predefined format (user id and password) and submits the authentication (dialog or form) back the the server, which then invokes the appropriate security logic (more on this shortly). Neither Tomcat nor the web application care whether the origin of the data was a dialog or a form beyond the simple configuration option in web.xml.
If/when the credentials are approved, the original URL request is taken off the siding by the server and internally re-submitted, making the whole login process transparent to the application.
Once authenticated, the application will see values in two HttpServletRequest properties that were previously null. One is the userPrincipal, the other is the remoteUser. The remoteUser is the user ID that was authenticated. The userPrincipal contains what is effectively a "black box", but the interface that UserPrincipal objects presents can be queried to get the remoteUser, so getRemoteUser is a convenience method.
An authenticated user has zero or more roles associated. The user-to-role mapping is external to the webapp. The web.xml file indicates what roles can access a given URL pattern, plus application code can query to see if the current user has a necessary role. Failure to possess the requisite role means that application logic should reject the requested function, or in the case of URL mappings handled by the container, the container itself will reject the request (and return a FORBIDDEN page).
So the role map is roughly speaking J2EE's equivalent of .htaccess. The URL role mappings in web.xml correspond (more or less) to an Apache Location directive with access controls specified. Since the access control is done via URL patterns, it's actually the URL that determines access, NOT the filesystem location of static content. However, the default handling of URLs not associated with servlets or JSPs is to convert them to WAR-relative paths, so, for example, the URL pattern for "*.jpg" files in the WAR's images directory would be something like "/images/*.jpg". Note the leading slash. It's important. A URL's root is the root of the WAR, not the root of the filesystem.
The actual backing store (or equivalent) for J2EE in Tomcat is the Realm. Realms are plug-compatible modules that contain the necessary methods to authenticate and role-check. The simplest one is probably the MemoryRealm, which reads the TOMCAT_HOME/conf/tomcat-users.xml file to get the list of userids, passwords and user/role mappings. Production systems typically use a JDBC or LDAP Realm. Because the Realms all implement the same interface, you can use MemoryRealm for testing and LDAP for production without modifying the webapp at all - even web.xml, since the Realm is defined externally (in the Context). I've also worked with custom Realms that used Web Services and there are Realms for Single Signon, lockout of repeat offenders and even stacking multiple Realms (which can be useful if in-house users are in Active Directory and external users are defined in a database).
Some additional notes. First, BASIC authentication isn't all that common in J2EE. The primary reason being that it's a real pain to log out without closing the entire browser. Secondarily there are concerns about the security of transport of the login credentials.
Science is the process of replacing what we "know" with what is TRUE. Politics, alas, often prefers to be the opposite.
If I may add to Tim's excellent explanation, it's worth knowing that JEE supports 4 types of authentication. He's already mentioned Basic which only uses Base64 encryption. Easily cracked. Bad idea.
Digest is the next method. It's more secure but not supported by all containers. If you are on Tomcat 6 or better, you can use this. I'm not sure about 5.x.
The next is Client-Cert. Very secure but the cost and hassle of using signed certificates usually keeps this method rather limited. Business to business transactions mostly.
All the above use a dialog box to login. The last method, Form, allows you to create your own html login form, but it offers no encryption at all. You must use SSL if you are going to use Form based authentication.
Head First Servlets and JSP has an excellent chapter on using JEE authentication and authorization. If you don't have a copy, you need one. It's one of those books that should be in every web developers library.
"The good news about computers is that they do what you tell them to do. The bad news is that they do what you tell them to do." -- Ted Nelson