Security annotations

Annotations are a powerful programming mechanism resulting from the JSR-175 recommendation. An annotation is a standard way to include supported security behaviors while allowing, the source code and configuration files to be generated automatically.

In Java™ Platform, Enterprise Edition (Java EE) 5 and later, The security roles and policies can be defined using annotations as well as within the deployment descriptor. During the installation of the application, the security policies and roles defined using annotations are merged with the security policies and roles defined within the deployment descriptor. This merge is performed by the Annotations Metadata Manager (AMM) facility. When the metadata is merged, the following inheritance rules are followed.
Table 1. Metadata merger inheritance rules .

This table lists the metadata merger inheritance rules.

Scenario Rules
Security metadata in deployment descriptor only No merge is needed, the security metadata from the deployment descriptor is propagated.
Security metadata in annotations only No merge is needed, the security metadata defined with annotations is propagated.
Security metadata in deployment descriptor and annotations The metadata from the deployment descriptor and annotations is merged. The metadata in annotations is overridden by the same type of data from the deployment descriptor.
Six security annotations are currently supported. For each annotation, a MergeAction implementation is defined.
  • @DeclareRoles (Servlet 2.5 and greater and EJB 3)

    The MergeAction implementation finds all the classes annotated with the DeclareRoles annotation. Within each annotated class for each role name specified, if the security roles listed in the deployment descriptor does not contain a SecurityRole with the annotated role name, a new SecurityRole is created and added to this list of security roles.

  • @RunAs (Servlet 2.5 and greater and EJB 3)

    The MergeAction implementation finds all the classes with the RunAs annotation. For each annotated class, it finds the Servlet or the Enterprise Java Bean (EJB) associated with the given class. It then determines if a run-as element is defined in the deployment descriptor for the servlet or EJB. If one is not found, a new run-as element is created and added to the deployment descriptor. If a run-as element is found, this run-as element will be used instead of creating a new one. The role name used in the RunAs annotation must be defined in the deployment descriptor.

  • @DenyAll (EJB 3 only)

    The MergeAction implementation finds all the methods annotated with the DenyAll annotation. For each annotated method, if the method is not included in the deployment descriptor list of excluded methods, and a MethodPermission does not exist in the deployment descriptor, a new MethodElement is created and added to this list of excluded methods in the deployment descriptor.

  • @PermitAll (EJB 3 only)

    The MergeAction implementation finds all the classes and the methods with the PermitAll annotation. For each annotated class, it finds the Enterprise Java Bean (EJB) associated with the given class. It then searches the subset of the MethodElements in the list of all the MethodPermissions defined in the deployment descriptor for this EJB. If a MethodElement with a wildcard method name (“*”) is not found and a wildcard method does not exist in the list of excluded methods or in the list of MethodElements with security roles, a new MethodPermission and a new MethodElement are created. The new MethodPermission is marked unchecked and is added to the MethodPermission list in the deployment descriptor. The new MethodElement is added to the MethodElement list of the newly created unchecked MethodPermission. Similar action is done for all annotated methods. Instead of a wildcard MethodElement, the method signature must match exactly the signature of the annotated method.

  • @RolesAllowed (EJB 3 only)

    The MergeAction implementation finds all of the classes and methods with the RolesAllowed annotation. For each annotated class, it finds the EJB associated with the given class. It then finds the subset of the MethodElements in the list of all the MethodPermissions defined in the deployment descriptor for this EJB. If a MethodElement with a wildcard method name (“*”) is not found, and a wildcard method does not exist in the list of excluded methods or in the list of unchecked MethodElements, a new MethodPermission and MethodElement are created. If a MethodPermission for this EJB exists with exactly the same roles as those found in the annotation, this MethodPermission will be used instead of creating a new one. For each role name specified in the annotation, a new SecurityRole is created and added to the SecurityRole list in the MethodPermission, If the MethodPermission was newly created, it is added to the MethodPermission list in the deployment descriptor. The new MethodElement created is added to the MethodElement list of the MethodPermission. Similar processing is done for all annotated methods. Instead of a wildcard MethodElement, the method signature must exactly match the signature of the annotated method. Additionally, for each role name specified in the annotation, if the deployment descriptor list of security roles does not contain a SecurityRole with the annotated role name, a new SecurityRole is also created and added to this list of security roles.

  • @ServletSecurity (Servlet 3.0 only)
    Note: Support for ServletSecurity annotation for Servlet 3.0 is new in this release of WebSphere® Application Server.

    When an application deploys, the ServletSecurity MergeAction implementation finds all servlets with the ServletSecurity annotation. For each annotated servlet, it finds the servlet associated with the given class base on the WebServlet annotation. If RolesAllowed in the ServletSecurity annotation is not found in the deployment descriptor, it then creates a role-name attribute for the role in the deployment descriptor.

    When an application starts, the WebContainer inspects all servlets with the RunAs, declareRoles, and ServletSecurity annotations, and sets those annotations on the setServletSecurity() method of the ServletRegistration annotation. The WebContainer notifies the security component to inspect all ServletRegistration annotations that have URL patterns and security constraints. The security component then determines if a URL pattern is defined in the deployment descriptor. If one is not defined in the deployment descriptor, the security constraints and RunAs role in the URL pattern are created and then used. If an exact match is already defined in the deployment descriptor, the security constraints and RunAs role in the URL pattern of the deployment descriptor are used instead of the annotation data.

    Note: When the web authentication system property, com.ibm.wsspi.security.web.webAuthReq, is set to persisting, you can log into an unprotected URL if a valid username and password are provided.

    The Inherited servlet annotation is a metadata annotation. Do not specify the Inherited annotation in the class. If a subclass does not have security annotation, it automatically inherits security annotation from the parent class. The subclass can overwrite the parent security annotations by specifying its security annotations.

    The following example is for all HTTP methods with no constraints:
    @WebServlet ("/Example") 
    @ServletSecurity
    public class Example extends HttpServlet {
           ……
    }
    The following example is for all HTTP methods with no <auth-constraint> element and confidential TransportGuarantee required:
    @WebServlet ("/Example")
    @ServletSecurity(@HttpConstraint(transportGuarantee =
                          TransportGuarantee.CONFIDENTIAL))
    public class Example extends HttpServlet { 
           ……
    }
    The following example is for all HTTP methods with all access denied:
    @WebServlet ("/Example")
    @ServletSecurity(@HttpConstraint(EmptyRoleSemantic.DENY))
    public class Example extends HttpServlet {
           ……
    }
    The following example is for all HTTP methods except for the GET and POST values with no constraints. For GET, the <auth-constraint> element requires membership in ALL ROLE. For POST, all access is denied.
    @WebServlet (name="Example", urlPatterns={"/Example"}) 
    @ServletSecurity((httpMethodConstraints = {
    	@HttpMethodConstraint(value = "GET", rolesAllowed = “ALL ROLE"),
    	@HttpMethodConstraint(value="POST“, emptyRoleSemantic =
    EmptyRoleSemantic.DENY))
    })
    public class Example extends HttpServlet {
           ……
    }
    The following example is for all HTTP methods except GET, the <auth-constraint> element requires membership in ALL ROLE, and the GET method has no constraints.
    @WebServlet (name="Example", urlPatterns={"/Example"}) 
    @ServletSecurity(value = @HttpConstraint(rolesAllowed = "ALL ROLE"),
    	httpMethodConstraints = @HttpMethodConstraint("GET"))
    public class Example extends HttpServlet {
           ……
    }
    The following example is for all HTTP methods except TRACE, the <auth-constraint> element requires membership in ALL ROLE, and for TRACE, all access is denied.
    @WebServlet (name="Example", urlPatterns={"/Example"})
    @ServletSecurity(value = @HttpConstraint(rolesAllowed = "ALL ROLE"),
    	httpMethodConstraints = @HttpMethodConstraint(value="TRACE",
    	emptyRoleSemantic = EmptyRoleSemantic.DENY))
    public class Example extends HttpServlet {
           ……
    }