Implementing Application Security


The sample application uses a container-provided authentication and authorization mechanism. The servlet specification prescribes declarative security, which is the means of expressing an application's security structure including roles, access control, and authentication requirements in a form external to the application. For the sample application, the security configuration is specified declaratively in the deployment descriptor (web.xml) using the <security-constraint> element for protecting web resources as follows:

 <security-constraint>     <display-name>Administration Gateway</display-name>     <web-resource-collection>         <web-resource-name/>         <description>Administration Menu</description>         <url-pattern>/AdministratorServices.do</url-pattern>         <http-method>POST</http-method>         <http-method>GET</http-method>     </web-resource-collection>     <auth-constraint>         <description>Administrator Access</description>         <role-name>NPOAdministrator</role-name>         <role-name>PortalAdministrator</role-name>         <role-name>SiteAdministrator</role-name>     </auth-constraint> </security-constraint> 

In this deployment descriptor specification, the resource identified by the <url-pattern> element (/AdministatorServices.do) is protected by the container from unauthorized access. The security constraints apply to the specified HTTP methods. Only users in the role specified by the <role-name> (within <auth-constraint>) specification will be able to access this resource. The security constraints are effective only when the client tries to directly access the protected resources; resources are not protected when a servlet invokes another resource using the RequestDispatcher.forward() or RequestDisptacher.include().

It is advisable to control resource access using container provided authentication and authorization because the process of requesting user credentials, validating and maintaining login credentials, and subsequently tracking access to requested resources is provided by the container based on standards established for providing these services. This significantly reduces custom code and leverages the security solutions provided by vendors. J2EE application servers use the JAAS (Java Authentication and Authorization Service) framework for providing user authentication, and for enforcing access control. The JAAS authentication framework is based on Pluggable Authentication Module (PAM), and therefore supports an architecture that allows system administrators to plug in the appropriate authentication services to meet their security requirements. With the availability of new or updated authentication services, system administrators can easily plug them in without having to change existing applications. To write your own LoginModule for the JAAS framework, please refer to http://java.sun.com/j2se/1.4/docs/guide/security/jaas/JAASLMDevGuide.html, and http://java.sun.com/security/jaas/doc/api.html. Container vendors also provide useful templates as a starting point for writing JAAS extensions. JAAS was also discussed in Chapter 3.

The sample application uses the default security realm provided by the container; this security realm has limitations, but one could write custom JAAS LoginModules or procure a vendor-provided extension that seamlessly plugs into the JAAS framework. This style of managing security employs container-managed authentication and authorization, which makes the code portable across different vendor implementations. Also, third-party vendors provide support for JAAS framework, thus enabling wider choice of security solutions.

The sample application also employs programmatic security. Programmatic security is provided using the following methods of the HttpServletRequest interface:

  • getRemoteUser

  • isUserInRole

  • getUserPrincipal

The getRemoteUser method returns the username that was used in the login page. The login page is shown to an unauthenticated remote user when the user tries to access a protected resource. Form-based authentication is used when a developer wants to control the look and feel of the login screen. The login form must contain fields with the name j_username for entering a username, and j_password for entering the password; the action of the login form must always be j_security_check. The login form used by the sample application is shown here. Refer to AdministratorLogin.jsp for complete code.

 <form method="POST" action="j_security_check" name="adminLogin">   <table border="0" cellspacing="0" cellpadding="5">     <tr>       <td ><bean:message key="Login.AdministratorID"/></td>       <td><input type="text" name="j_username" size="16", maxlength="16"></td>     </tr>     <tr>       <td ><bean:message key="Login.Password"/></td>       <td><input type="password" name="j_password" size="16" maxlength="16"></td>     </tr>     <tr>       <td>&nbsp;</td>       <td><html:submit><bean:message key="prompt.submit"/><html:submit></td>     </tr>   </table> </form> 

When the user tries to access a protected resource, the container will send the login form to the user. Once the user posts the username and password to the server, the container will attempt to authenticate the user. Upon successful authentication the container will redirect the user, along with the original request parameters, to the resource originally requested; the redirection to the requested resource will occur only if the user is in the role authorized for accessing the resource. Form-based authentication is usually used with a secure transport mechanism like SSL (using HTTPS protocol). In order to use HTTPS, specify <user-data-constraint> in the deployment descriptor as follows.

 <security-constraint>     <display-name>Administration Gateway</display-name>     <web-resource-collection>     ... rest of the declarations ...     </web-resource-collection>     <auth-constraint>     ... rest of the declarations ...     </auth-constraint>     <user-data-constraint>         <transport-guarantee>CONFIDENTIAL</transport-guarantee>     <user-date-constraint> </security-constraint> 

If the original request was over HTTP, and CONFIDENTIAL is specified, the container will redirect the client to the HTTPS port. For further information on switching between the HTTP and HTTPS protocols using the Struts framework, please refer to http://sslext.sourceforge.net.

The Ffollowing declarations are used in the web.xml file to specify a login page that uses form-based authentication:

 <login-config>     <auth-method>FORM</auth-method>     <realm-name>myrealm</realm-name>     <form-login-config>         <form-login-page>/1_3_AdministratorLogin.jsp</form-login-page>         <form-error-page>/1_3_AdministratorLoginFailure.jsp</form-error-page>     </form-login-config> </login-config> 

Other forms of authentication include basic, digest, and client authentication. Please refer to the URL http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Security.html for further information.

The use of isUserInRole determines if a remote user is in a specified security role. A group is a collection of users; users within a group inherit the access privileges assigned to the group. Roles are assigned either at the group level or user level. The container enforces access to resources based on roles. We saw previously how this is accomplished using the <auth-constraint> declarations in the deployment descriptor.

The System Administrator creates groups and users (called principals) in the security realm. Please refer to Chapter 9 for complete details on setting up groups and users in the security realm. The principal-to-role mapping is declared in the WebLogic-specific deployment descriptor weblogic.xml as follows:

 <security-role-assignment>     <role-name>NPOAdministrator</role-name>     <principal-name>NPOAdmin</principal-name> </security-role-assignment> <security-role-assignment>     <role-name>PortalAdministrator</role-name>     <principal-name>PortalAdmin</principal-name> </security-role-assignment> <security-role-assignment>     <role-name>SiteAdministrator</role-name>     <principal-name>SiteAdmin</principal-name> </security-role-assignment> 

During code construction, developers can freely choose role names for use in programs; at deployment time, roles created by the system administrator are mapped to the ones defined by the developer using the following mapping in web.xml.

System administrator–defined roles are listed below here:

 <security-role>     <role-name>SiteAdministrator</role-name> </security-role> <security-role>     <role-name>PortalAdministrator</role-name> </security-role> <security-role>     <role-name>NPOAdministrator</role-name> </security-role> 

The following is the mapping of system administrator–defined roles and roles used in the programs:

 <servlet>     ... rest of the declarations ...     <security-role-ref>         <role-name>SiteAdminRole</role-name>         <role-link>SiteAdministrator</role-link>     </security-role-ref>     <security-role-ref>         <role-name>PortalAdminRole</role-name>         <role-link>PortalAdministrator</role-link>     </security-role-ref>     <security-role-ref>         <role-name>NPOAdminRole</role-name>         <role-link>NPOAdministrator</role-link>     </security-role-ref> </servlet> 

The sample application uses three different roles, as illustrated in the preceding snippet. These three roles influence the application logic in how the Views are selected and processed, and how the resulting form data is handled. The sample application uses a special pattern to handle programmatic security, as illustrated by the following code:.

 public class AdminLoginAction extends Action {     public ActionForward execute( ActionMapping mapping,     ActionForm form, HttpServletRequest req,     HttpServletResponse res ) throws Exception {         HttpSession session = req.getSession( true );         if ( req.isUserInRole( "SiteAdminRole" ) ) {             session.setAttribute( "GreaterCause.AdminRole",                 "SiteAdminRole" );         }         else if ( req.isUserInRole( "PortalAdminRole" ) ) {             session.setAttribute( "GreaterCause.AdminRole",                 "PortalAdminRole" );         }         else if ( req.isUserInRole( "NPOAdminRole" ) ) {             session.setAttribute( "GreaterCause.AdminRole",                 "NPOAdminRole" );         }         return mapping.findForward( "success" );     } } 

The AdminLoginAction class is invoked by the Struts controller when access to the protected resource 2_SiteAdministratorServicesMainPage.jsp is attempted. The corresponding declaration in the struts-config.xml file is shown here:

 <action path="/AdministratorServices"         type="com.gc.prez.common.AdminLoginAction">     <forward name="success"         path="/2_SiteAdministratorServicesMainPage.jsp" redirect="false"/> </action> 

At first glance, it may seem that AdminLoginAction is redundant because it simply provides a mapping between the role names used in the web.xml file to the role names used in the application. Although not demonstrated in the AdminLoginAction class, this class has been designed based on the fact that many eCommerce applications have to rely on runtime variables and user entitlements for dynamically configuring a user-centric process flow; isUserInRole() is not adequate in such scenarios. AdminLoginAction provides a hook for evaluating other runtime parameters in deciding the most appropriate system behavior tailored to the user's environment rather than just the role name. The sample application leverages the information saved in the session to define a custom hasAccess tag to provide dynamic behavior in views (JSPs); this tag is used for controlling the formatting and processing of HTML forms, as shown here:

 <gc:hasAccess role="SiteAdminRole">     <html:link page="/PortalAllianceRegistration.do?action=Create">         <bean:message key="SiteAdminServices.PortalRegistration"/>     </html:link><br>     <html:link page="/NPORegistration.do?method=ShowNPORegistrationForm">         <bean:message key="SiteAdminServices.NPORegistration"/>     </html:link><br><br> </gc:hasAccess> 

This snippet is extracted from 2_AdministrativeServicesNavBar, which is a highly dynamic navigation bar that is created based on a user's role. The <gc:hasAccess> tag will test the role, and if the role matches the one specified by the role attribute, then the body of the tag will be evaluated. The GreaterCause tag library containing the hasAccess tag is specified in the deployment descriptor as follows:

 <taglib>     <taglib-uri>/WEB-INF/GreaterCause.tld</taglib-uri>     <taglib-location>/WEB-INF/GreaterCause.tld</taglib-location> </taglib> 

Using the <gc:has Access> tag, the 2_AdministrativeServicesNavBar produces three different views for the three administrator roles, as illustrated in Figure 5-3, Figure 5-4, and Figure 5-5.

click to expand
Figure 5-3: Site Administrator Services

click to expand
Figure 5-4: Portal Administrator Services

click to expand
Figure 5-5: NPO Administrator Services

In the sample application, the various administrator-related functions are grouped together based on the <auth-constraint> specifications that list the authorized role names. To prevent any attempts by assailants to defeat the access mechanism tailored by the navigation bar, we specify the following constraints in the web.xml to prevent unauthorized access to protected resources:

 <security-constraint>    ... declarations to protect /AdministratorServices.do ... </security-constraint> <!-- Declarations to protect PortalAdministrator functions --> <security-constraint>     <display-name>Portal Alliance Administration</display-name>     <web-resource-collection>         <web-resource-name/>         <description>Portal Alliance Management Functions</description>         <url-pattern>/PortalAllianceRegistration.do</url-pattern>         <url-pattern>/ManagePortalAlliance.do</url-pattern>         <url-pattern>/CreateCampaignStep1.do</url-pattern>         <url-pattern>/CreateCampaignStep2.do</url-pattern>         <url-pattern>/UpdateCampaignsStep1.do</url-pattern>         <url-pattern>/UpdateCampaignsStep2.do</url-pattern>         <http-method>POST</http-method>         <http-method>GET</http-method>     </web-resource-collection>     <auth-constraint>         <role-name>SiteAdministrator</role-name>         <role-name>PortalAdministrator</role-name>     </auth-constraint> </security-constraint> <security-constraint>     ... declarations to protect NPOAdministrator functions ... </security-constraint> 

The Java Servlet Specification Version 2.3, Chapter SRV.13 provides detailed information on the various elements of the deployment descriptor.




Practical J2ee Application Architecture
Practical J2EE Application Architecture
ISBN: 0072227117
EAN: 2147483647
Year: 2003
Pages: 111
Authors: Nadir Gulzar

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net