Recipe 3.9 Restricting Requests for Certain Servlets
You want to allow only authenticated users to request certain servlets.
Use the security-constraint element in the web.xml deployment descriptor.
Some web applications contain servlets that should not be invoked directly by web users, because they handle sensitive data and may have special jobs (such as administering the server or web application). For example, you could design a servlet that is accessed only by server administrators. How do you protect these servlets from being invoked improperly or by unauthorized users?
In the latter case, you can use declarative security , or container-managed security . This strategy involves configuring the web.xml deployment descriptor with your application's security information, thereby decoupling security information from your servlet's code. Any security changes for a web application can then be made in the XML configuration files (or via the WebLogic Server 7.0 Administration Console) without messing with the servlet's source code. The security configuration is then loaded and implemented by the servlet container.
You can also use programmatic security , which involves including security- related code within servlets, such as checking the HttpServletRequest object to see if a user is authorized to use a certain web resource.
For Tomcat, using the security-constraint element in web.xml requires creating a username and password in the XML file located at <Tomcat-installation-directory>/conf/ tomcat-users .xml . This is an XML file in which you define internal users and passwords. It might look like Example 3-13.
Example 3-13. A tomcat-users.xml file
<?xml version='1.0' encoding='utf-8'?> <tomcat-users> <role rolename="manager"/> <role rolename="tomcat"/> <role rolename="developer"/> <user username="tomcat" password="tomcat" roles="tomcat,manager"/> <user username="bruce" password="bruce1957" roles="tomcat,manager,developer"/> <user username="stacy" password="stacy1986" roles="tomcat"/> </tomcat-users>
This XML fragment includes a tomcat-users root element containing one or more role and user elements, depending on how many users are defined for the web applications handled by that instance of Tomcat. This tomcat-users.xml configuration file is accessible by all of the contained web applications.
You then create security-constraint , login-config , and security-role elements inside of the web application's deployment descriptor, or web.xml .
The security-constraint element looks like Example 3-14, given that the protected URL pattern in this case is <url-pattern>/CookieServlet</url-pattern> .
Example 3-14. The security-constraint element
<security-constraint> <web-resource-collection> <web-resource-name>CookieInfo</web-resource-name> <url-pattern>/CookieServlet</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <description>This applies only to the "developer" security role</description> <role-name>developer</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint>
The security-constraint element must contain one or more web-resource-collection elements. The web-resource-collection element describes which web resources in the web application are protected by the specified security constraint. In other words, a request over the Internet for a web resource, such as a servlet, triggers any security constraint that has been mapped to the resource. In this example, the security constraint protects any request that fits the URL pattern, <web-application-root-directory>/CookieServlet . The http-method elements specify the HTTP methods that this security constraint covers. In the example, a GET or POST request for /CookieServlet triggers the configured security mechanism. If you do not include any http-method elements under the security-constraint element, the constraint will apply to any HTTP method (such as PUT or DELETE , in addition to GET and POST ).
The auth-constraint element is designed to describe the security roles that permit access to the web component. A security role is a name that represents the security privileges a user or group of users have in relation to a particular resource, such as a servlet. Examples of security roles are admin , manager , or developer . In the case of the tomcat-users.xml file, users are assigned to roles. Within the security-constraint element example, only users that are mapped to the developer role in the tomcat-users.xml file have access to CookieServlet .
How does a web application authenticate a user in the first place? For instance, how can the web application find out the requester's username and password, and thereby determine if he can be given access to the servlet? In container-managed security, this is what the login-config element is used for. This element appears after the security-constraint element in the web.xml file. Both elements might look like Example 3-15 in a web application's deployment descriptor.
Example 3-15. Using login-config with a security-constraint element
<security-constraint> <web-resource-collection> <web-resource-name>CookieInfo</web-resource-name> <url-pattern>/CookieServlet</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <description>This applies only to the "developer" security role</description> <role-name>developer</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> </login-config> <security-role> <role-name>developer</role-name> </security-role>
The login-config element specifies the authentication method that is used to authenticate any user requests for protected web resources. Protected web resources are those specified by a web-resource-collection element, inside the security-constraint element. In the example, BASIC authentication is used for any requests that match the URL pattern /CookieServlet . BASIC is a familiar form of web authentication in which the browser presents the user with a dialog window for entering the username and password. Tomcat compares the given name and password with the user information configured in the tomcat-users.xml file, and then uses the web application's security-constraint configuration to determine whether the user can access the protected servlet.
One more ingredient is necessary to complete this servlet security configuration: the security-role element. Example 3-15 creates a security role named developer . The developer value also appears in the security-constraint child element auth-constraint . This means that only users who are mapped to the security role developer are able to access web resources which are protected by the security constraint (i.e., that are identified by a web-resource-collection child element of security-constraint ). In other words, this authentication method is actually a two-step process:
The users are mapped to security roles in Tomcat in the previously mentioned tomcat-users.xml file. Here is an example of what a user element might look like in the tomcat-users.xml file:
<username="bwperry" password="bruce2002" roles="developer,standard,manager" />
This user is assigned three different roles: developer , standard , and manager . The Tomcat servlet container uses these XML elements in the tomcat-users.xml file to determine whether certain username/password combinations have been assigned particular roles. Figure 3-1 is designed to unravel these confusing cross-references. Just think of a security role as a way to further refine a group of application users, or group them in terms of their user privileges.
Figure 3-1. Using a security constraint element
The security configuration depicted by Example 3-15s XML text can be used with WebLogic 7.0, but the WebLogic-specific configuration file is called weblogic.xml .
Example 3-16 shows the XML within the weblogic.xml deployment descriptor.
Example 3-16. Security role in weblogic.xml
<!-- weblogic.xml security role mapping --> <security-role-assignment> <role-name>developer</role-name> <principal-name>bwperry</principal-name> </security-role-assignment>
In WebLogic 7.0, you can also establish users, groups, and security roles that are global to a particular WebLogic server through the Administrative Console.
This recipe described how to restrict the requests for certain servlets. The next recipe shows one way to prevent all requests except those forwarded from a controller servlet from reaching other servlets.
Chapter 1 on web.xml ; Recipe 3.1-Recipe 3.8; Chapter 11 of the Servlet v2.3 and 2.4 specifications on mapping requests to servlets; the Core J2EE Blueprints page: http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html