Controlling security using declarations

Declarative security allows users, defined by roles, to access methods of a class. This is accomplished using a series of annotations to permit either certain roles to use a method, to permit all roles to use a method, or to deny access for all roles.

Getting ready

The application developer needs to determine which users (roles) should be permitted to access which methods. Once this has been determined, the classes and methods are annotated to affect these decisions.

Declarative security can be achieved using any of several annotations including @RolesAllowed, @PermitAll, and @DenyAll annotations. Each of these annotations has restrictions on where they can be used.

Annotation

Use With

Description

@PermitAll

Bean, Method

Allows access by all users

@DenyAll

Method

No roles are permitted access to the method

@RolesAllowed

Bean, Method

A list of roles permitted access

The steps used to control access include:

  1. Specifying the role permitted using one of the above annotations
  2. Applying the annotation at the desired level

How to do it...

The @RolesAllowed is configured with either a single string or an array of strings. These strings are the names of the roles allowed access to the EJB or a method. When applied to a method, the assignment will override any class level assignment. Here the use of both an array and a single role are specified.

@RolesAllowed({"bankemployee", "bankcustomer"})
@RolesAllowed("bankemployee")

In the VoucherManager EJB, add an @RolesAllowed annotation to both the approve and reject methods. Specify a role of manager.

@RolesAllowed("manager")
public boolean approve() {
voucher.setApproved(true);
return true;
}
@RolesAllowed("manager")
public boolean reject() {
voucher.setApproved(false);
return false;
}

Next, modify the SecurityServlet's processRequest method's try block to create a voucher and approve it using the approve method. Also, display a message to indicate whether the voucher was approved or not and add a catch block at the end of the try block to handle any access exceptions. The javax.ejb.EJBAccessException is thrown when an access restriction is violated.

voucherManager.createVoucher("Susan Billings", "SanFrancisco", BigDecimal.valueOf(2150.75));
boolean voucherApproved = voucherManager.approve();
...
if(voucherApproved) {
out.println("<h3>Voucher was approved</h3>");
} else {
out.println("<h3>Voucher was not approved</h3>");
}
...
catch(EJBAccessException e) {
System.out.println("Access exception");
}

Execute the servlet and enter "mary" as the user. The application should execute normally with the voucher being approved since "mary" is authorized to use the approve method as shown in the following screenshot:

How to do it...

Close the browser and re-execute the servlet. This time, use "sally" as the user. Since "sally" is not authorized to use the approve method, an EJBAccessException is thrown.

INFO: Access exception

The @PermitAll annotation permits access to the EJB or a specific method by all roles. Anyone is able to access and use such methods. This is the default annotation for methods. For example, the VoucherManager's getName method is not annotated. Add the following statement to the SecurityServlet immediately after the code which displays the voucher approval message.

out.println("<h3>Voucher name: " + voucherManager.getName() + "</h3>");

Execute the servlet using "mary". The voucher's username is displayed as illustrated in the following screenshot:

How to do it...

If we add the @PermitAll annotation to the getName method we will see no change in behavior. So what is the use of this annotation?

At the class level, one or more roles may have been declared using the @DeclareRoles annotation. The @PermitAll annotation can be used to permit a method to be used by some role other than those declared at the class level. For example, use the following annotations for the VoucherManager EJB:

@Stateful
@DeclareRoles("manager")
@RolesAllowed("manager")
public class VoucherManager {
...
}

In the SecurityServlet, remove the code dealing with the submit method.

try {
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet SecurityServlet</title>");
out.println("</head>");
out.println("<body>");
voucherManager.createVoucher("Susan Billings", "SanFrancisco",
BigDecimal.valueOf(2150.75));
out.println("<h3>Voucher name: " + voucherManager.getName() + "</h3>");
out.println("</body>");
out.println("</html>");
}
catch(EJBAccessException e) {
System.out.println("Access exception");
}
finally {
out.close();
}

Next, use the @RolesAllowed("manager") annotation only for the VoucherManager's approve and reject methods. Do not use annotations for any of the other methods. If the servlet is executed using a user in the manager role ("mary"), the application executes cleanly. However, if you log in as "sally", an exception occurs because "sally" is no longer an authorized user. This is to be expected.

Add the @PermitAll annotation to the createVoucher and getName methods. Re-execute the application using "sally". This time the application should execute correctly. While we have only specified the manager role for the class, the @PermitAll annotation allows other groups to use those methods.

The @DenyAll annotation denies access to all roles and users. However, this annotation has limited utility. If access to the method should be denied to all users, then it can easily be removed from the EJB.

How it works...

The @PermitAll, @DenyAll, and @RolesAllowed annotations provided an easy-to-use mechanism for controlling access to methods based upon the user's role. When an unauthorized user attempted to access a method, an exception was thrown which was caught and dealt with.

However, sometimes it is necessary to allow an unauthorized user access to a method under certain conditions. The need for this access and how to achieve it is detailed in the next recipe.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.79.176