While doing some research on securing JAX-RS Restful services, I came across this question on stackoverflow which asks how best to wire up a simple security mechanism for:

  1. Jersey JAX-RS.
  2. Tomcat.
  3. Basic Authentication.
  4. JSR 250 Annotations such as @RolesAllowed.

So in a nutshell….this can be accomplished quite easily by configuring the following:

  1. tomcat-users.xml (found in the conf dir of your tomcat install).
  2. the applications web.xml.
  3. and lastly annotating the restful service.

By adjusting the tomcat-users.xml  you will create a tomcat memory realm of usernames and passwords.

To do this…simpy add the following to the tomcat-users.xml file:


<role rolename="admin" />
<user username="admin" password="adminadmin" roles="manager,admin,user" />
<role rolename="user" />
<user username="user" password="useruser" roles="user" />
Next you will want to adjust your web.xml to include both jersey resources and also the applications security configuration:
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure</web-resource-name>
<url-pattern>/resources/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Test</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
and lastly a rest service that utilizes the JSR-250 security annotations:
import com.sun.jersey.core.util.Base64;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;

@Path("/Test")
@RolesAllowed("admin")
public class Test {

    @GET
    @Produces("text/plain")
    @RolesAllowed("user")
    public String getNumber(@Context HttpHeaders headers){
        System.out.println( getCredentials(headers));

        return "1 Secured with User";
    }

     @GET
     @Path("/Secure")
     @RolesAllowed("admin")
     @Produces("text/plain")
    public String getSecureNumber(@Context HttpHeaders headers){
         System.out.println( getCredentials(headers));

        return "2 Secured with Admin";
    }

    private String getCredentials(HttpHeaders headers) {
        String auth = headers.getRequestHeader("authorization").get(0);

        auth = auth.substring("Basic ".length());
        String[] values = new String(Base64.base64Decode(auth)).split(":");
        String username = values[0];
        String password = values[1];

        String return_val = "Username = " + username + " Password = "+ password;

        return return_val;
    }

}

If you deploy to localhost with the above configuration the urls are as follows

  1. an “admin” person has access to  http://localhost:8080/MyService2/resources/Test/Secure
  2. a “user” person has access to = http://localhost:8080/MyService2/resources/Test/

Because this is “BASIC” security…a pop up will appear to log the person in when a request is made to the secured resource.

You can find a zipped copy of my Netbeans project here