Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

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

Secure thread collaboration across protection domains

Build solid applications with the AccessControlContext and the GuardedObject classes

  • Print
  • Feedback

Page 2 of 4

Security at the extremes

Let's consider again the two scenarios described above. Both situations present two threads, and therefore two contexts. The two threads will likely execute code from different protection domains as well. For example, in Situation 1, the server thread must belong to a protection domain with permission to access all files in the filesystem, while the client thread must belong to a protection domain with a more restrictive set of permissions.

The Java security model provides two mechanism for dealing with situations like those presented in the introduction: the AccessControlContext class and the GuardedObject class.

Let's look at each and examine how they solve these security problems.

Class AccessControlContext

The AccessControlContext class encapsulates a static snapshot of an execution context. The getContext() method on the AccessController class creates an AccessControlContext instance for the current execution context.

The following code illustrates how to use AccessControlContext in the context of Situation 1.

public
static
class Client
implements Runnable
{
    private
    Server m_server = null;
    public
    void
    link(Server server)
    {
      if (m_server != server)
      {
        m_server = server;
        m_server.link(this);
      }
    }
    public
    void
    run()
    {
      for (int i = 0; i < 10; i++)
      {
        Server.Message message = new Server.Message("/tmp/out.tmp", Integer.toString(i) + '\n');
        m_server.logMessage(message);
      }
    }
  }
  public
  static
  class Server
  implements Runnable
  {
    private
    Client m_client = null;
    public
    void
    link(Client client)
    {
      if (m_client != client)
      {
        m_client = client;
        m_client.link(this);
      }
    }
    private
    LinkedList m_linkedlist = new LinkedList();
    public
    synchronized
    void
    logMessage(Message message)
    {
      message.m_accesscontrolcontext = AccessController.getContext();
      m_linkedlist.add(message);
      notifyAll();
    }
    private
    synchronized
    Message
    retrieveMessage()
    throws InterruptedException
    {
      while (m_linkedlist.isEmpty()) wait();
      return (Message)m_linkedlist.removeFirst();
    }
    public
    void
    run()
    {
      while (true)
      {
        Message message = null;
        try
        {
          message = retrieveMessage();
        }
        catch (InterruptedException interruptedexception)
        {
          break;
        }
        final String stringDestination = message.m_stringDestination;
        final String stringMessage = message.m_stringMessage;
        AccessController.doPrivileged
        (
          new PrivilegedAction()
          {
            public
            Object
            run()
            {
              FileWriter filewriter = null;
              try
              {
                filewriter = new FileWriter(stringDestination, true);
                filewriter.write(stringMessage);
                filewriter.close();
              }
              catch (IOException ioexception)
              {
                ioexception.printStackTrace();
              }
              return null;
            }
          },
          message.m_accesscontrolcontext
        );
      }
    }
    public
    static
    class Message
    {
      private
      AccessControlContext m_accesscontrolcontext = null;
      private
      String m_stringDestination = null;
      private
      String m_stringMessage = null;
      public
      Message(String stringDestination, String stringMessage)
      {
        m_stringDestination = stringDestination;
        m_stringMessage = stringMessage;
      }
    }
  }


The preceding code contains two threads, identified as the client and the server. The server thread writes messages to logs, which correspond to files in the local filesystem -- a log is specified by its path and filename. The requirements state that there are many logs, some of which the client thread can write to and some of which it can't.

  • Print
  • Feedback

Resources