Home arrow Java arrow Page 5 - Securing Struts Applications
JAVA

Securing Struts Applications


Web applications often require that certain parts of the system be secured. Some security requirements can be satisfied with standard security mechanisms, while others call for a customized approach. Sometimes, as a developer, you may need to use a combination of these two techniques. This article helps you examine the issues and techniques. It is excerpted from chapter 19 of the book The Complete Reference: Struts, written by James Holmes (McGraw-Hill/Osborne, 2004; ISBN: 0072231319 ).

Author Info:
By: McGraw-Hill/Osborne
Rating: 5 stars5 stars5 stars5 stars5 stars / 111
September 15, 2005
TABLE OF CONTENTS:
  1. · Securing Struts Applications
  2. · Using Container-Managed Security
  3. · BASIC Login
  4. · FORM-Based Login
  5. · Application-Managed Security
  6. · Page/Action-Level Security Checks
  7. · Using Cookies
  8. · SSLEXT to the Rescue

print this article
SEARCH DEVARTICLES

Securing Struts Applications - Application-Managed Security
(Page 5 of 8 )

If container-managed security is not sufficient for your application, then you need consider creating your own security structure. Generally, you need to address the same issues in application-managed security that are addressed in container-managed security:

  • How and when do you authenticate the users?
  • What determines the authorization levels?
  • Is there a guest user and, if so, what privileges does that user have?
  • Does the application need to support HTTPS for transmission of sensitive data?

The following sections look at several ways of handling these issues. As you read through them, you will apply your knowledge to the Mini HR application. Most of this discussion applies to Java-based Web applications in general—not just Struts-based applications.

Creating a Security Service

Using application-managed security requires different skills and knowledge than are required to use a container-managed approach. For application-managed security, you need to rely on traditional “best practices” development. For use with Mini HR, you will create a SecurityService interface API that will act as a façade for whatever underlying implementations exist. The definition of the interface to meet the needs of the Mini HR application is shown here:

package com.jamesholmes.minihr.security;
public interface SecurityService {
  public User authenticate(String username, String password)
    throws AuthenticationException;
}

Next is a sample implementation that uses a HashMapto store the user data in memory. Of course, a real implementation would retrieve this data from a persistent store such as a file system, relational database, or LDAP server.

package com.jamesholmes.minihr.security;
import java.util.HashMap;
import java.util.Map;
public class SecurityServiceImpl implements SecurityService {
  private Map users;
  private static final String ADMIN_ROLE = "administrator";
 
public SecurityServiceImpl() {
    users = new HashMap();
    users.put("bsiggelkow",
     
new User( "bsiggelkow","Bill", "Siggelkow", "thatsme",
        new String[] {ADMIN_ROLE}));
    users.put("jholmes",
      new User( "jholmes","James", "Holmes", "maindude", 
        new String[] {ADMIN_ROLE}));
    users.put("gburdell",
      new User( "gburdell","George", "Burdell", "gotech",
        new String[] {ADMIN_ROLE}));
  }
 
public User authenticate(String username, String password)
    throws AuthenticationException
  {
    User user = (User) users.get(username);
    if (user == null)
     
throw new AuthenticationException("Unknown user");
    boolean passwordIsValid = user.passwordMatch(password);
    if (!passwordIsValid)
     
throw new AuthenticationException("Invalid password");
    return user;
  }
}

This interface provides the basic security services. The authenticate( )method verifies the user’s password and returns an object that represents the user. For the authorization needs of the application, there are different alternatives. While it may be tempting to engineer a complete role-based infrastructure, a more pragmatic approach is to provide a mechanism to determine if a user is an administrator. Following is the object that will hold the user data:

package com.jamesholmes.minihr.security; 
import java.io.Serializable;
public class User implements Serializable {
  private String firstName;
  private String lastName;
  private String username;
  private String password;
  private String[] roles;
 
public User(String name, String fName, String lName,
    String pwd, String[] assignedRoles) {
    username = name;
    firstName = fName;
    lastName = lName;
    password = pwd
    roles = assignedRoles;
 
}
 
public String getUsername() {
    return username;
  }
 
public String getFirstName() {
    return firstName;
  }
 
public String getLastName() {
    return lastName;
  }
 
public boolean passwordMatch(String pwd) {
    return password.equals(pwd);
 
}
 
public boolean hasRole(String role) {
    if (roles.length > 0) {
      for (int i=0; i<roles.length; i++) {
        if (role.equals(roles[i])) return true;
     
}
    }
    return false;
 
}
 
public boolean isAdministrator() {
    return hasRole("administrator");
  }
}

Notice that some basic information that can be used for personalization, such as the user's first and last name, has been included. In addition, the isAdministrator( ) method indicates whether or not the user is an administrator. Also a hasRoll( ) method has been implemented that will indicate whether or not a user has been assigned a given role. This method will be useful with customized Struts role processing. To tie this custom security service into the application, you also need to create a LoginAction that will process the user login, as shown in the following code. A LogoutAction that allows a user to log out of the application is also created by the following code. A logout action typically needs to just invalidate the user’s session. While you cannot force a user to log out, it is important to provide this feature, particularly if your application is accessible from a public terminal.

package com.jamesholmes.minihr; 
import javax.servlet.http.*;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.struts.action.*;
import com.jamesholmes.minihr.security.*;
public final class LoginAction extends Action {
 
public ActionForward execute(ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws Exception
 
{
    HttpSession session = request.getSession();
    String username =
    
(String) PropertyUtils.getSimpleProperty(form, "username");
    String password =
     (String) PropertyUtils.getSimpleProperty(form,"password");
   
SecurityService service = new SecurityServiceImpl();
    User user = service.authenticate(username, password);
    session.setAttribute("User", user);
    // Forward control to this Action's success forward
    return mapping.findForward("success");
 
}
}

First, the action gets the username and password from the login form. Then, it calls the authenticate method of the security service. The returned user is then stored in the session. The exception handling is performed using Struts’ declarative exception handling. Back at the index page, you need to change it from the container-managed implementation as shown in the following example. In this case, you want to check the administrator bean property of the user and display the link only if the value is true. Note also that you must explicitly check whether the User object is in the session. This handles the case where the user has not yet been authenticated.

<%@ taglib uri="/WEB-INF/tlds/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/tlds/struts-logic.tld" prefix="logic" %>
 
<html>
<head>
 
<title>ABC, Inc. Human Resources Portal</title>
</head>
<body>
<font size="+1">ABC, Inc. Human Resources Portal</font><br>
<logic:notPresent name="user" scope="session">
<hr width="100%" noshade="true">
<html:form action="/login">
Username: <html:text property="username"/><br/>
Password: <html:password property="password"/><br/>
<html:submit value="Login"/>
</html:form>
<html:errors/>
</logic:notPresent>
<hr width="100%" noshade="true">
<ul>
<logic:present name="user" scope="session">
<logic:equal name="user" property="administrator" value="true">
<li><html:link forward="add">Add an Employee</html:link><li>
</logic:equal>
</logic:present>
<li><html:link forward="search">Search for Employees</html:link></li>
</ul>
</body>
</html>

The important modification to this index page is the use of the <logic:present> tag to hide or show the login form. In addition, the <logic:equal> tag is used to hide or show the Add an Employee link. You are not finished, however. First, remove (or comment out) the container-managed security sections from the web.xml file. Then, remove the roles attribute from the add.do action mapping.

You are not done yet, however. Notice that there is now nothing to prevent someone who is not an administrator from adding a new employee. Anyone can browse directly to the Add an Employee page and submit the form. In addition, although securing the add.jsp page is not critical, it is imperative that you secure the AddAction (add.do). What you need to do is implement the checks that were in place with container-managed security. There are several alternatives to consider.


blog comments powered by Disqus
JAVA ARTICLES

- Java Too Insecure, Says Microsoft Researcher
- Google Beats Oracle in Java Ruling
- Deploying Multiple Java Applets as One
- Deploying Java Applets
- Understanding Deployment Frameworks
- Database Programming in Java Using JDBC
- Extension Interfaces and SAX
- Entities, Handlers and SAX
- Advanced SAX
- Conversions and Java Print Streams
- Formatters and Java Print Streams
- Java Print Streams
- Wildcards, Arrays, and Generics in Java
- Wildcards and Generic Methods in Java
- Finishing the Project: Java Web Development ...

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials