I really shouldn't have used the
word "folder". That's more appropriate to GUI desktop environments. It would have been more accurate to say "directory". Or more properly "filesystem directory", since "directory" in an enterprise environment can also apply to things like JNDI.
There are 2 views of a WAR.
One view is the developer's view. The WAR is a ZIP (JAR) file when distributed according to the
J2EE spec. Tomcat allows working with an unzipped (exploded) copy of the WAR, but other than how it lives on the server's disk drive, the difference is no difference.
The other view is the application user's view. The important thing to remember here is an old familiar mantra of mine:
A web server is not a file server.
You cannot use a filesystem open method in code running on the client machine to access resources that are in the server machine. You cannot use any of the filesystem function calls, in fact. To access a web resource, the client must open a pair of network sockets, one for sending, one for receiving. The sending socket's destination is the web server, including a port number (80 for standard WWW, 8080 for default Tomcat, 443 for SSL, and so forth). Once the connection is open, the client must send a text data stream that conforms to a rigidly-defined specification. Specifically, the HTTP 1.1 spec as defined in the HTTP RFC, or one of the related supported RFC's (such as HTTP 1.0). The first line of that stream includes a command (generally GET or POST) and a Uniform Resource Locator (URL).
On the receiving side, the server (Tomcat) listens for connection requests on its ports (8080, 8443, and so forth). When a request is made, it opens up a receiving socket and accepts the HTTP data stream coming from the client. It parses the data stream, starting with the URL. The URL is dissected to determine a webapp context, and, if the context matches one of the contexts defined as webapps to Tomcat, the data stream is switched over to application request processing.
Before the data actually hits the webapp, however, it goes through several intermediaries, both standard and optional. In Tomcat, typically these are Valves and you can even write your own, if needed. One of those intermediaries is the container-managed authorization mechanism, which will get involved if the webapp's web.xml indicates that container managed authentication and authorization is in use.
The container-managed authorization mechanism does a
pattern match against the incoming URL, stripped of the server/context parts. The patterns it uses are those which were supplied in the webapp's web.xml. If there's a hit, the authorization mechanism first checks to see if the requester is logged in. If not, the whole request is sidelined, the login form defined in web.xml is posted back to the requester, and the requester interacts with the login process. Once logged in, the original request is pulled back off the sidelines and proceeds as though nothing had happened.
Well, almost nothing. Once a user is logged in, he/she/whatever has an associated set of security roles. The URL pattern that matches the original URL request also specifies a set of roles. If there's an intersection between the two, the request is passed down the processing pipeline and eventually to the webapp. If there isn't a match between user roles and authorized roles, the request is rejected on the spot, a "forbidden" error is raised, and the request never gets anywhere near the webapp (other than maybe having a custom 403 page displayed).
When the request reaches the webapp proper, it's going to be matched up by URL pattern to see if it matches a
servlet's URL pattern defined in web.xml or an implicit pattern definition made by compiling a
JSP to product a corresponding JSP servlet. If there's a match, the request - which at this point is going to have been distilled into a J2EE Http(Servlet)Request - enters the servlet's service() method which typically routes it to a doGet or doPost method.
It's been a long trip. but at last the client request has arrived at the developer-written code or some facsimile thereof. Note that at no time up to now have I referred to directories or even folders. The URL is simply a text
string containing various amusing bits of information. The security manager doesn't look at the URL from the point of view of a filesystem architecture, only as a string to be sliced and diced and used as a basis for applying rules digested from the appropriate application's web.xml file.
The confusing thing about URLs and resources is that resources are files and directories (folders) in a virtual filesystem based on the WAR. But webapp clients cannot access resources directly, because a web server is not a file server. Despite the fact that URLs typically have lots of slashes in them, URLs are strings. It's up to the webapp to interpret those strings. For example, in
JSF, if I define a URL pattern such as "/faces/*" and bind it to the FacesServlet, Tomcat will route any URL requests containing the "/faces/" segment immediately following the host/port/context part of the URL to the FacesServlet. The FacesServlet will then dissect the incoming URL, pull off the View name and use that to look up the resource that defines the View. This is how a request like "/faces/secured/SecureIndex.jsp" can be used to serve up a View whose template is stored as a WAR resource under "/secured/SecureIndex.jsp". Or, if you prefer the "*.jsf" URL pattern, how "/secured/SecureIndex.js
f is resolved by using the WAR's View template resource "/secured/SecureIndex.js
p".
It's also how you can accept URLs that correspond to no file at all and return completely dynamic content such as generated charts and other graphics or "on-the-fly" PDF's.
But wait - there's one last kink in the process. Webapps usually contain a lot of completely static content such as CSS, images and JavaScript files. In a 100% pure .environment, the requests for each of these types of resources would require a servlet to process the requests. However, this would be a nuisance, so there's an implicit servlet provided by the webapp server (Tomcat) that gets control when an incoming URL doesn't match any of the explicit servlet URL patterns in web.xml or the implicit URL patterns corresponding to compiled JSPs. This implicit servlet takes the part of the URL following the host/port/context ID, up but excluding the delimiter of the service pattern (in other words, it chops off the "?parameter=" or "#" or ";jsessionid" or whatever). This segment of the URL is then used by the implicit servlet to locate the corresponding WAR resource so that, for example URL "/images/ballon.gif" locates the WAR resource "/images/ballon.gif". The implicit servlet then copies the resource byte-for-byte out to the response output stream, along with the usual freight (MIME type, cookies and so forth).
Finally, at long last, the response is returned to the client. Assuming that the incoming URL passed the security system.
Hopefully this makes the distinction between URL paths and WAR resource paths a little clearer and why it is that container security cannot protect WAR resources directly, but only URLs that would attempt to access them. Making sure that the only URLs that access them are protected is up to you.