|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 6
In the Java Security API, there is a package, java.security.acl, that contains several classes that you can use to establish a security system in Java. These classes enable your development
team to specify different access capabilities for users and user groups. All code used in this example can be found in Resources.
The concept is fairly straightforward. A user or user group is granted permission to functionality by adding that user or
group to an access control list. For example, consider a java.security.Principal called testUser as shown below:
Principal testUser = new PrincipalImpl ("testUser");
Now you can create a Permission object to represent the capability of reading from a file.
Permission fileRead = new PermissionImpl ("readFile");
Once you have created the user and the user's permission, you can create the access control list entry. It's important to note that the security APIs require that the owner of the access list be passed in order to ensure that this is truly the developer's desired action. It is essential that this owner object be protected carefully.
Acl accessList = new AclImpl (owner, "exampleAcl");
In its final form, the access list will contain a bunch of access list entries. You can create these as follows:
AclEntry aclEntry = new AclEntryImpl (testUser); aclEntry.addPermission(fileRead); accessList.addEntry(owner, aclEntry);
The preceding lines create a new AclEntry object for the testUser, add the fileRead permission to that entry, and then add the entry to the access control list.
You can now check the user permissions quite easily, as follows:
boolean isReadFileAuthorized = accessList.checkPermission(testUser, readFile);
The preceding examples show how a form-based authentication scheme can work, how the EJB model can restrict access based on a username/password combination, and how you can use the access control lists within the Java security model to restrict access to functionality. I now intend to leverage these examples to demonstrate an overall system approach to the security problem.
In the first example, the form-based authentication scheme was implemented in a rudimentary fashion. It checked only to ensure that the user was contained in the database of authenticated users. A user contained in the database was granted access to all functionality within the system without further definition.
In the second example, the EJB authorized the user attempting to execute restricted methods on the bean. This security protects the bean from unauthorized access, but does not protect the Web application.
In the third example, I discussed the Java Security Access Control package. I demonstrated how you could use a simple API to verify that a user had access to certain functionality within the system.
By gathering these three examples, you can create a simple authentication scheme that limits the user's access to Web-based components of a system, including back-office systems.
The goal of this next example is to demonstrate the collective power of these three security mechanisms and to provide a pattern by which you can build more advanced security frameworks. All code used in this example can be found in Resources.
The first step in this example is to create delegate classes to wrap the security functionality contained in the Java Access Control Model classes. By wrapping the method calls and interfaces, the developer can ensure that the majority of the code in the system can function independently of the security implementation. In addition, through the Delegation pattern, the remainder of the code can perform security functionality without obtaining specific knowledge of the inner workings of Sun's security model.
The first major component of this example is the User. The code that implements the interface can delegate calls to the java.security.Principal interface. In addition to the methods contained in the Principal interface, the User interface will blueprint other methods for obtaining or modifying information related to a given system user.
For example, to retrieve a user's telephone number, you could implement a method called getPhoneNumber(). Another approach to obtaining this user data involves the use of XML. You could convert data stored in the database into
an XMLDocument from which data could be accessed by walking the tree. This example does not delve into either approach in great detail,
leaving it to the reader as an exercise.
The second major component I'll discuss is the Feature. The classes that implement this interface use the implementation of the java.security.acl.Permission interface to perform their functionality. In a Web-based system, there is a need to identify both the name of the action
(for example, "run report") and the URL related to that action.
Although this is possible through the Java security model, you have to store both attributes in a single String and then parse for the individual attributes. While this works, it is dependent on the formatting, which can vary at runtime,
rather than on a compiled interface as has been developed here.
The last major component is the WebSecurityManager object. This object is responsible for performing the duties related to user management, features management, and the access
control lists that establish the relationships between users and features.
You can implement the WebSecurityManager in many ways including, but not limited to, a Java bean used by JSP, a servlet, an EJB, or a CORBA/RMI service. The choice
is up to the system's designer who must satisfy customer requirements. In this simple example, the WebSecurityManager is assumed to run in the same JVM as the servlets/JSP.
In the last section, I introduced the important objects of this scheme. In this section, I'll further develop the interactions of these objects.
For the sake of this example, let's make two assumptions: first, the information relating the users and their permissions is stored in a relational database as opposed to an LDAP or an external object repository; second, this database is already populated. By making the second assumption, I am limiting the scope of this article to the retrieval of users from the database; the process of storing users is performed identically but in the opposite direction.