Annotations to secure Java EE applications

You can provide security for your Java™ EE enterprise application directly in your source code using annotations.
Common security annotations: JSR 250 defines a number of common security annotations. Five security annotations are defined:
  • javax.annotation.security.PermitAll:
    • Can be used at type or method level.
    • Indicates that the given method or all business methods of the given EJB are accessible by everyone.
  • javax.annotation.security.DenyAll:
    • Can be used at method level.
    • Indicates that the given method in the EJB cannot be accessed by anyone.
  • javax.annotation.security.RolesAllowed:
    • Can be used at type or method level.
    • Indicates that the given method or all business methods in the EJB can be accessed by users that are associated with the list of roles.
  • javax.annotation.security.DeclareRoles:
    • Can be used at type level.
    • Defines roles for security checking. To be used by EJBContext.isCallerInRole, HttpServletRequest.isUserInRole, and WebServiceContext.isUserInRole.
  • javax.annotation.security.RunAs:
    • Can be used at type level.
    • Specifies the RunAs role for the given components.

Using security annotations

  • For the annotations @PermitAll, @DenyAll, and @RolesAllowed, a class-level annotation applies to a class and a method-level annotation applies to a method. Method-level annotation overrides the behavior of class level annotation.
    	@Stateless
    	@RolesAllowed("team")
    	public class TestEJB implements Test {
    		@PermitAll
    		public String hello(String msg) {
    			return "Hello, " + msg;
    		}
    
    		public String goodbye(String msg) {
    			return "Goodbye, " + msg;
    		}
    	}
     

    In this example, the hello() method is accessible by everyone, and the goodbye() method is accessible by users of role team.

  • The @DeclareRoles annotation defines a list of roles to be used by a given component. In the Java EE 5 or 6 environment, you can look up the resource by using the @javax.annotation.Resource and verify whether the user is of the given role by invoking the following APIs:
    Table 1. . API used by Java EE component
    Component API used to check role
    EJB javax.ejb.EJBContext.isCallerInRole(role)
    Servlet javax.servlet.http.HttpServletRequest.isUserInRole(role)
    Web Service javax.xml.ws.WebServiceContext.isUserInRole(role)
  • The @PermitAll, @DenyAll, and @RolesAllowed annotations allow you to implement most of the authorization decision. However, to accomplish more complicated logic, use the @DeclareRoles annotation. For example, suppose the hello method is to be accessible by a user who is in role A and who is not in role B at the same time. The following code clip achieves this goal:
    	@Stateless
    	@DeclaresRoles({"A", "B"})
    	public class TestEJB implements Test {
    		@Resource private SessionContext sc;
    		public String hello(String msg) {
    			if (sc.isCallerInRole("A") && !sc.isCallerInRole("B")) {
    				...
    			} else {
    				...
    			}
    		}
    	}
     

Invalid use of security annotations

  • More than one of @DenyAll, @PermitAll, @RolesAllowed cannot apply to the same method. For example, the following usage is not valid:
    	@PermitAll
    	@DenyAll
    	public String test()
     
  • Two @RolesAllowed annotations cannot apply to the same methods. For example, the following usage is not valid and fails in compilation:
    	@RolesAllowed("team")
    	@RolesAllowed("otherteam")
    	public String hello()
    Instead, use this structure:
    	@RolesAllowed({"team", "otherteam"})
    	public String hello()

Feedback