Fork me on GitHub

Simple. Java. Security.

Apache Shiro JAX-RS Support

Apache Shiro’s JAX-RS support is built on top of the more general Servlet support, and requires Shiro’s Servlet Filter to be setup. The Servlet Filter can be setup by using Shiro’s Servlet fragment, web.xml configuration, or programmatically.

Dependencies

Include the shiro-servlet-plugin and shiro-jaxrs dependencies in you application classpath (we recomend using a tool such as Apache Maven or Gradle to manage this).

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-servlet-plugin</artifactId>
    <version>1.7.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-jaxrs</artifactId>
    <version>1.7.0</version>
</dependency>
compile 'org.apache.shiro:shiro-servlet-plugin:1.7.0'
compile 'org.apache.shiro:shiro-jaxrs:1.7.0'

For information on other ways to set up the Apache Shiro Filter see the web documentation.

Configuration

There are two basic approaches used to define the authentication and authorization for your JAX-RS resources: paths defined statically in configuration, or via annotations on your resource.

If you are using Guice or Spring see those docs on how to configure Shiro.

Just like any other web application, your resources paths can be defined in a shiro.ini file. For example, to require resources under /api/secured to use basic authentication, your [urls] section would look like:

[urls]

/api/secured/** = authcBaic

See the web documentation for more details.

The other, probably more popular, option is to use Shiro’s annotations along side other JAX-RS annotations on your resources. However you MUST still define at least one path in your shiro.ini file.

The below code block will allow for basic authentication but NOT require it (via the permissive flag). This way all of the resources under /api can optional require authentication and authorization based on annotations.

[urls]

/api/** = authcBaic[permissive]

Example

To create a simple example we can define a JAX-RS resource HelloShiro:

@Path("/shiro")
public class HelloShiro {

  @GET
  @RequiresUser
  public String sayHelloShiro() {
      return "Hello!";
  }
  
  @GET
  @Path("define")
  @RequiresPermissions("hello:define")
  public String defineShiro() {
      return  "Shiro is the Japanese term for a castle";
  }
}

This resource has two end points, the first allows access by any logged in user, the second any user with the permission hello:define.

The corresponding JAX-RS Application class:

@ApplicationPath("/api")
public class ExampleApp extends Application {

@Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<>();

        // register the Shiro Feature
        classes.add(ShiroFeature.class);

        // register resources:
        classes.add(HelloShiro.class);

        return classes;
    }
}

The ShiroFeature does three things:

In the above example, requests to either /api/shiro or /api/shiro/define will return an HTTP status of 401 if a user is not currently logged in. A request to /api/shiro/define made by a user without the hello:define will return a 403.

Want to see more?

You can find portable JAX-RS application that runs with Jersey, RestEasy or Apache CXF in the samples directory on Github.