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.
Also note that Tomcat does several things when it shifts to secured mode for a user. First, the jsessionId changes. Not the HttpSession itself, but the jsessionId value that lets Tomcat know which user is which (and therefore which HttpSession object to use). Secondly, Tomcat is very paranoid, so by default it will stuff in extra headers that suppresses caching of images, javascript and other static objects. If you don't want it to do that, you have to undo it yourself. I did it in a ServletFilter, but there may be a Tomcat Valve available, at least for more recent Tomcat versions.