Authorization code in java

Authorization code in java

This tutorial expands the program and policy file developed in the JAAS Authentication Tutorial tutorial to demonstrate the JAAS authorization component, which ensures the authenticated caller has the access control rights (permissions) required to do subsequent security-sensitive operations. Since the authorization component requires that the user authentication first be completed, please read the JAAS Authentication Tutorial tutorial first if you have not already done so.

The rest of this tutorial consists of the following sections:

If you want to first see the tutorial code in action, you can skip directly to Running the Authorization Tutorial Code and then go back to the other sections to learn more.

What is JAAS Authorization?

JAAS authorization extends the existing Java security architecture that uses a security policy (see Default Policy Implementation and Policy File Syntax) to specify what access rights are granted to executing code. That architecture is code-centric . That is, the permissions are granted based on code characteristics: where the code is coming from and whether it is digitally signed and if so by whom. We saw an example of this in the sampleacn.policy file used in the JAAS Authentication Tutorial tutorial. That file contains the following:

grant codebase "file:./SampleAcn.jar" < permission javax.security.auth.AuthPermission "createLoginContext.Sample"; >; 

This grants the code in the SampleAcn.jar file, located in the current directory, the specified permission. (No signer is specified, so it doesn’t matter whether the code is signed or not.)

JAAS authorization augments the existing code-centric access controls with new user-centric access controls. Permissions can be granted based not just on what code is running but also on who is running it.

When an application uses JAAS authentication to authenticate the user (or other entity such as a service), a Subject is created as a result. The purpose of the Subject is to represent the authenticated user. A Subject is comprised of a set of Principal s, where each Principal represents an identity for that user. For example, a Subject could have a name Principal («Susan Smith») and a Social Security Number Principal («987-65-4321»), thereby distinguishing this Subject from other Subject s.

Permissions can be granted in the policy to specific Principal s. After the user has been authenticated, the application can associate the Subject with the current access control context. For each subsequent security-checked operation (a local file access, for example), the Java runtime will automatically determine whether the policy grants the required permission only to a specific Principal and if so, the operation will be allowed only if the Subject associated with the access control context contains the designated Principal .

How is JAAS Authorization Performed?

To make JAAS authorization take place, the following is required:

  • The user must be authenticated, as described in the JAAS Authentication Tutorial tutorial.
  • Principal -based entries must be configured in the security policy; see How Do You Make Principal-Based Policy File Statements?
  • The Subject that is the result of authentication must be associated with the current access control context; see How Do You Associate a Subject with an Access Control Context?.
Читайте также:  Https sdo urgaps ru login index php

How Do You Make Principal-Based Policy File Statements?

Policy file grant statements (see Default Policy Implementation and Policy File Syntax can now optionally include one or more Principal fields. Inclusion of a Principal field indicates that the user or other entity represented by the specified Principal , executing the specified code, has the designated permissions.

Thus, the basic format of a grant statement is now

 grant signer(s) field>, codeBase URL> Principal field(s)> < permission perm_class_name "target_name", "action"; . permission perm_class_name "target_name", "action"; >; 

where each of the signer , codeBase and Principal fields is optional and the order between the fields doesn’t matter.

A Principal field looks like the following:

Principal Principal_class "principal_name" 

That is, it is the word Principal (where case doesn’t matter) followed by the (fully qualified) name of a Principal class and a principal name.

A Principal class is a class that implements the java.security.Principal interface. All Principal objects have an associated name that can be obtained by calling their getName method. The format used for the name is dependent on each Principal implementation.

The type of Principal placed in the Subject created by the basic authentication mechanism used by this tutorial is SamplePrincipal , so that is what should be used as the Principal_class part of our grant statement’s Principal designation. User names for SamplePrincipal s are of the form name , and the only user name accepted for this tutorial is testUser , so the principal_name designation to use in the grant statement is testUser .

It is possible to include more than one Principal field in a grant statement. If multiple Principal fields are specified, then the permissions in that grant statement are granted only if the Subject associated with the current access control context contains all of those Principal s.

To grant the same set of permissions to different Principal s, create multiple grant statements where each lists the permissions and contains a single Principal field designating one of the Principal s.

The policy file for this tutorial includes one grant statement with a Principal field:

grant codebase "file:./SampleAction.jar", Principal sample.principal.SamplePrincipal "testUser" < permission java.util.PropertyPermission "java.home", "read"; permission java.util.PropertyPermission "user.home", "read"; permission java.io.FilePermission "foo.txt", "read"; >; 

This specifies that the indicated permissions are granted to the specified Principal executing the code in SampleAction.jar . (Note: the SamplePrincipal class is in the sample.principal package.)

How Do You Associate a Subject with an Access Control Context?

To create and associate a Subject with the current access control context, you need the following:

  • The user must first be authenticated, as described in JAAS Authentication Tutorial.
  • The static doAs method from the Subject class must be called, passing it an authenticated Subject and a java.security.PrivilegedAction or java.security.PrivilegedExceptionAction . (See Appendix A: API for Privileged Blocks in Permissions in the JDK for a comparison of PrivilegedAction and PrivilegedExceptionAction.) The doAs method associates the provided Subject with the current access control context and then invokes the run method from the action. The run method implementation contains all the code to be executed as the specified Subject. The action thus executes as the specified Subject. The static doAsPrivileged method from the Subject class may be called instead of the doAs method, as will be done for this tutorial. In addition to the parameters passed to doAs , doAsPrivileged requires a third parameter: an AccessControlContext. Unlike doAs , which associates the provided Subject with the current access control context, doAsPrivileged associates the Subject with the provided access control context or with an empty access control context if the parameter passed in is null , as is the case for this tutorial. See doAs vs. doAsPrivileged in the JAAS Reference Guide for a comparison of those methods.
Читайте также:  Test

The Authorization Tutorial Code

The code for this tutorial consists of four files:

  • SampleAzn.java is exactly the same as the SampleAcn.java application file from the JAAS Authentication Tutorial tutorial except for the additional code needed to call Subject.doAsPrivileged .
  • SampleAction.java contains the SampleAction class. This class implements PrivilegedAction and has a run method that contains all the code we want to be executed with Principal -based authorization checks.
  • SampleLoginModule.java is the class specified by the tutorial’s login configuration file (see The Login Configuration File for the JAAS Authorization Tutorial) as the class implementing the desired underlying authentication. SampleLoginModule ‘s user authentication consists of simply verifying that the name and password specified by the user have specific values. This class was also used by the JAAS Authentication Tutorial tutorial and will not be discussed further here.
  • SamplePrincipal.java is a sample class implementing the java.security.Principal interface. It is used by SampleLoginModule . This class was also used by the JAAS Authentication tutorial and will not be discussed further here.

The SampleLoginModule.java and SamplePrincipal.java files were also used in the JAAS Authentication Tutorial tutorial, so they are not described further here. The following sections describe the other source files

SampleAzn.java

Like SampleAcn , the SampleAzn class instantiates a LoginContext lc and calls its login method to perform the authentication. If successful, the authenticated Subject (which includes a SamplePrincipal representing the user) is obtained by calling the LoginContext ‘s getSubject method:

Subject mySubject = lc.getSubject(); 

After providing the user some information about the Subject , such as which Principal s it has, the main method then calls Subject.doAsPrivileged , passing it the authenticated Subject mySubject , a PrivilegedAction ( SampleAction ) and a null AccessControlContext , as described in the following.

The SampleAction class is instantiated via the following:

PrivilegedAction action = new SampleAction(); 

The call to Subject.doAsPrivileged is performed via:

Subject.doAsPrivileged(mySubject, action, null); 

The doAsPrivileged method invokes execution of the run method in the PrivilegedAction action ( SampleAction ) to initiate execution of the rest of the code, which is considered to be executed on behalf of the Subject mySubject .

Passing null as the AccessControlContext (third) argument to doAsPrivileged indicates that mySubject should be associated with a new empty AccessControlContext . The result is that security checks occurring during execution of SampleAction will only require permissions for the SampleAction code itself (or other code it invokes), running as mySubject . Note that the caller of doAsPrivileged (and the callers on the execution stack at the time doAsPrivileged was called) do not require any permissions while the action executes.

package sample; import java.io.*; import java.util.*; import java.security.Principal; import java.security.PrivilegedAction; import javax.security.auth.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; import javax.security.auth.spi.*; import com.sun.security.auth.*; /** * This Sample application attempts to authenticate a user * and executes a SampleAction as that user. * * If the user successfully authenticates itself, * the username and number of Credentials is displayed. */ public class SampleAzn < /** * Attempt to authenticate the user. * * @param args input arguments for this application. These are ignored. */ public static void main(String[] args) < // Obtain a LoginContext, needed for authentication. Tell it // to use the LoginModule implementation specified by the // entry named "Sample" in the JAAS login configuration // file and to also use the specified CallbackHandler. LoginContext lc = null; try < lc = new LoginContext("Sample", new MyCallbackHandler()); >catch (LoginException le) < System.err.println("Cannot create LoginContext. " + le.getMessage()); System.exit(-1); >catch (SecurityException se) < System.err.println("Cannot create LoginContext. " + se.getMessage()); System.exit(-1); >// the user has 3 attempts to authenticate successfully int i; for (i = 0; i < 3; i++) < try < // attempt authentication lc.login(); // if we return with no exception, authentication succeeded break; >catch (LoginException le) < System.err.println("Authentication failed:"); System.err.println(" " + le.getMessage()); try < Thread.currentThread().sleep(3000); >catch (Exception e) < // ignore >> > // did they fail three times? if (i == 3) < System.out.println("Sorry"); System.exit(-1); >System.out.println("Authentication succeeded!"); Subject mySubject = lc.getSubject(); // let's see what Principals we have Iterator principalIterator = mySubject.getPrincipals().iterator(); System.out.println("Authenticated user has the following Principals:"); while (principalIterator.hasNext()) < Principal p = (Principal)principalIterator.next(); System.out.println("\t" + p.toString()); >System.out.println("User has " + mySubject.getPublicCredentials().size() + " Public Credential(s)"); // now try to execute the SampleAction as the authenticated Subject PrivilegedAction action = new SampleAction(); Subject.doAsPrivileged(mySubject, action, null); System.exit(0); > > /** * A CallbackHandler implemented by the application. * * This application is text-based. Therefore it displays information * to the user using the OutputStreams System.out and System.err, * and gathers input from the user using the InputStream System.in. */ class MyCallbackHandler implements CallbackHandler < /** * Invoke an array of Callbacks. * * @param callbacks an array of Callback objects which contain * the information requested by an underlying security * service to be retrieved or displayed. * * @exception java.io.IOException if an input or output error occurs. 

* * @exception UnsupportedCallbackException if the implementation of this * method does not support one or more of the Callbacks * specified in the callbacks parameter. */ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException < for (int i = 0; i < callbacks.length; i++) < if (callbacks[i] instanceof TextOutputCallback) < // display the message according to the specified type TextOutputCallback toc = (TextOutputCallback)callbacks[i]; switch (toc.getMessageType()) < case TextOutputCallback.INFORMATION: System.out.println(toc.getMessage()); break; case TextOutputCallback.ERROR: System.out.println("ERROR: " + toc.getMessage()); break; case TextOutputCallback.WARNING: System.out.println("WARNING: " + toc.getMessage()); break; default: throw new IOException("Unsupported message type: " + toc.getMessageType()); >> else if (callbacks[i] instanceof NameCallback) < // prompt the user for a username NameCallback nc = (NameCallback)callbacks[i]; System.err.print(nc.getPrompt()); System.err.flush(); nc.setName((new BufferedReader (new InputStreamReader(System.in))).readLine()); >else if (callbacks[i] instanceof PasswordCallback) < // prompt the user for sensitive information PasswordCallback pc = (PasswordCallback)callbacks[i]; System.err.print(pc.getPrompt()); System.err.flush(); pc.setPassword(System.console().readPassword()); >else < throw new UnsupportedCallbackException (callbacks[i], "Unrecognized Callback"); >> > >

SampleAction.java

SampleAction.java contains the SampleAction class. This class implements java.security.PrivilegedAction and has a run method that contains all the code we want to be executed as the Subject mySubject . For this tutorial, we will perform three operations, each of which cannot be done unless code has been granted required permissions. We will:

  • Read and print the value of the java.home system property,
  • Read and print the value of the user.home system property, and
  • Determine whether or not a file named foo.txt exists in the current directory.

Источник

Оцените статью