The Identity class represents an agent within the Security API. Identity implements the Principal interface, which is a generic representation of a person, group, or other named entity. An Identity has a name, which it inherits from the Principal interface, and other information that verifies the identity of the agent (a public key and assorted certificates, for example). A Signer is a subclass of Identity that also includes a private key that can be used to sign data. We'll discuss public and private keys and how they are created in more detail later in the chapter.
An Identity is created using a name for the agent being represented:
Identity fredsID = new Identity("Fred");
A public key and any available certificates can be added to Fred's identity to support the validity of his identity:
PublicKey fredsKey = ... // Get Fred's key Certificate fredsCert = ... // Get Fred's certificate Certificate fredsRSACert = ... // Get another certificate for Fred fredsID.setPublicKey(fredsKey); fredsID.addCertificate(fredsCert); fredsID.addCertificate(fredsRSACert);
If we are also able to sign data using Fred's identity, then we'll also have a private key for Fred, and we can create a Signer object for him:
Signer signingFred = new Signer("Fred"); PrivateKey fredsSigningKey = ... // Get Fred's private key PublicKey fredsPublicKey = ... // Get Fred's public key signingFred.setKeyPair(new KeyPair(fredsPublicKey, fredsSigning Key));;
The java.security.acl package includes interfaces that let you define specific access rights for individual agents or groups of agents. In the same style as the rest of the Security API, this package defines an API for access-control lists, with few of the interfaces actually implemented in the package. Sun has provided a default implementation of the ACL package in their sun.security.acl package. We'll use classes from Sun's implementation to demonstrate ACLs.
Central to the java.security.acl package is the Acl interface, which represents an access-control list. An Acl has a group of owners associated with it, represented by Principal objects. Principal is a term often used in security circles to refer to a user or agent acting as a party in a secure transaction. Since both Identity and Signer are subclasses of Principal, you can use instances of either wherever a Principal is called for. Only owners of the Acl are supposed to be able to modify the Acl. Implementations of the Acl interface should enforce this by checking the keys and certificates on the Principals of the owners, to be sure that the agent creating or modifying the ACL has access to the certified elements of the identity of one of the owners of the ACL.
Each entry in the access-control list is represented as an AclEntry object, which associates specific identities with the permissions they have over the resource being controlled. An entry is added to the Acl using the addEntry() method, which takes the Principal for the entity and its AclEntry as arguments.
Each AclEntry defines a set of permissions given to the Principal over the resource being protected. Specific types of permission are represented using the Permission interface, which doesn't actually implement any behavior, but acts as a placeholder for subclasses that distinguish permissions in application-specific ways (permission names, binary typecodes, etc.). The sun.security.acl package provides an implementation of Permission called PermissionImpl that uses strings to identify permission types (e.g., "READ", "WRITE").
The Principal for an AclEntry is set using the setPrincipal() method on the entry. Once this is done, permissions for the Principal are added to the entry using the addPermission() method:
// Define a set of permission types Permission read = new PermissionImpl("READ"); Permission create = new PermissionImpl("CREATE"); Permission update = new PermissionImpl("UPDATE"); Permission destroy = new PermissionImpl("DESTROY"); // Create some Principals Principal person1 = new PrincipalImpl("Fred"); Principal person2 = new PrincipalImpl("Sally"); // Make an entry for each principal AclEntry entry1 = new AclEntryImpl(person1); AclEntry entry2 = new AclEntryImpl(person2); // Give each principal their permissions: // Fred can only read the resource entry1.addPermission(read); // Sally can do anything entry2.addPermission(read); entry2.addPermission(create); entry2.addPermission(update); entry2.addPermission(destroy);
Notice that we've used PrincipalImpl objects to represent Principals in the Acl. The PrincipalImpl class is a subclass of the Principal interface provided in the sun.security.acl package. In a real application, we would probably use an Identity or Signer object to represent a principal in the Acl. This would allow us to verify a digital signature from a remote client before we would allow that remote client to access the resource protected by the Acl.
Once the AclEntrys have been created, they can be added to the Acl with the addEntry() method. The method takes two arguments: a Principal argument that corresponds to the owner of the Acl making the entry, and the AclEntry itself. For example:
Principal myID = ... // Get my identity Acl myAcl = ... // Create the Acl, setting me as an owner // Now add the entries created above. myAcl.addEntry(myID, entry1); myAcl.addEntry(myID, entry2);
With the ACL in place, we can check incoming agents for the necessary permissions to do specific actions. If an agent contacts our agent and asks to update a resource, we can check the ACL of that resource for write permission for that agent using their Principal:
Principal remoteAgent = ... // Initialize Principal for remote agent if (myAcl.checkPermission(remoteAgent, update)) { // Let the update action go through } else { // Disallow the action, and tell the agent // that it doesn't have the right permissions }
Copyright © 2001 O'Reilly & Associates. All rights reserved.