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.
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.
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]
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:
AuthorizationException
to HTTP status codes (401 and 403)Subject
as a java.security.Principal
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
.
You can find portable JAX-RS application that runs with Jersey, RestEasy or Apache CXF in the samples directory on Github.