8.1. Combining Container-Managed and Programmatic Security

Declarative security is very convenient: you set up usernames, passwords, access mechanisms (HTML forms vs. BASIC authentication) and transport-layer requirements (SSL vs. normal HTTP), all without putting any security-related code in any of the individual servlets or JSP pages. However, declarative security provides only two levels of access for each resource: allowed and denied. Declarative security provides no options to permit resources to customize their output depending on the username or role of the client that accesses them.

It would be nice to provide this customization without giving up the convenience of container-managed security for the usernames, passwords, and roles as would be required if a servlet or JSP page completely managed its own security (as in Section 8.3). To support this type of hybrid security, the servlet specification provides three methods in HttpServletRequest:

  • isUserInRole. This method determines if the currently authenticated user belongs to a specified role. For example, given the usernames, passwords, and roles of Listings 7.1 and 7.2 (Section 7.1), if the client has successfully logged in as user valjean, the following two expressions would return true.

    request.isUserInRole("lowStatus") 
    request.isUserInRole("nobleSpirited") 

    Tests for all other roles would return false. If no user is currently authenticated (e.g., if authorization failed or if isUserInRole is called from an unrestricted page and the user has not yet accessed a restricted page), isUserIn Role returns false. In addition to the standard security roles given in the password file, you can use the security-role-ref element to define aliases for the standard roles. See the next subsection for details.

  • getRemoteUser. This method returns the name of the current user. For example, if the client has successfully logged in as user valjean, request.getRemoteUser() would return "valjean". If no user is currently authenticated (e.g., if authorization failed or if isUserInRole is called from an unrestricted page and the user has not yet accessed a restricted page), getRemoteUser returns null.

  • getUserPrincipal. This method returns the current username wrapped inside a java.security.Principal object. The Principal object contains little information beyond the username (available with the getName method). So, the main reason for using getUserPrincipal in lieu of getRemoteUser is to be compatible with preexisting security code (the Principal class is not specific to the servlet and JSP API and has been part of the Java platform since version 1.1). If no user is currently authenticated, getUserPrincipal returns null.

It is important to note that this type of programmatic security does not negate the benefits of container-managed security. With this approach, you can still set up usernames, passwords, and roles by using your server’s mechanisms. You still use the login-config element to tell the server whether you are using form-based or BASIC authentication. If you choose form-based authentication, you still use an HTML form with an ACTION of j_security_check, a textfield named j_username, and a password field named j_password. Unauthenticated users are still automatically sent to the page containing this form, and the server still automatically keeps track of which users have been authenticated. You still use the security-constraint element to designate the URLs to which the access restrictions apply. You still use the user-data-constraint element to specify that certain URLs require SSL. For details on all of these topics, see Section 7.1.

Security Role References

The security-role-ref subelement of servlet lets you define servlet-specific synonyms for existing role names. This element should contain three possible subelements: description (optional descriptive text), role-name (the new synonym), and role-link (the existing security role).

For instance, suppose that you are creating an online bookstore and your server’s password file stipulates that user marty is in role author. However, you want to reuse a servlet of type BookInfo (in the catalog package) that was created elsewhere. The problem is that this servlet calls the role writer, not author. Rather than modifying the password file, you can use security-role-ref to provide writer as an alias for author.

Suppose further that you have a servlet of class EmployeeData (in the hr package) that provides one type of information to a goodguy and another type to a meanie. You want to use this servlet with the password file defined in Listings 7.1 and 7.2 (Section 7.1) that assign users to the nobleSpirited and meanSpirited roles. To accomplish this task, you can use security-role-ref to say that isUserInRole("goodguy") should return true for the same users that isUserInRole("nobleSpirited") already would. Similarly, you can use security-role-ref to say that isUserInRole("meanie") should return true for the same users that isUserInRole("meanSpirited") would.

Listing 8.1 shows a deployment descriptor that accomplishes both of these tasks.

Listing 8.1. web.xml (Excerpt illustrating security role aliases)
<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE web-app PUBLIC 
    "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" 
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> 

<web-app> 
  <!-- ... --> 
  <servlet> 
    <servlet-name>BookInformation</servlet-name> 
    <servlet-class>catalog.BookInfo</servlet-class> 
    <security-role-ref>
							<role-name>writer</role-name> <!-- New alias. --> 
      <role-link>author</role-link> <!-- Preexisting role. --> 
    </security-role-ref> 
  </servlet> 
  <servlet> 
    <servlet-name>EmployeeInformation</servlet-name> 
    <servlet-class>hr.EmployeeData</servlet-class> 
    <security-role-ref>
							<role-name>goodguy</role-name>       <!-- New. --> 
      <role-link>nobleSpirited</role-link> <!-- Preexisting. --> 
    </security-role-ref>
							<security-role-ref>
							<role-name>meanie</role-name>       <!-- New. --> 
      <role-link>meanSpirited</role-link> <!-- Preexisting. --> 
    </security-role-ref> 
  </servlet> 
  <!-- ... --> 
  <security-constraint>...</security-constraint> 
  <login-config>...</login-config> 
  <!-- ... --> 
</web-app> 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.118.90