= Integrating Apache Shiro into Spring-Boot Applications
:jbake-date: 2010-03-18 00:00:00
:jbake-type: page
:jbake-status: published
:jbake-tags: documentation, manual, spring
:idprefix:
:toc:

Shiro's Spring-Boot integration is the easiest way to integrate Shiro into a Spring-base application, for more general Spring Framework integration, take a the link:spring-framework.html[annotation] or link:spring-xml.html[XML] guides.

[#web_applications]
== Web Applications

Shiro has first-class support for Spring web applications. In a web application, all Shiro-accessible web requests must go through a main Shiro Filter. This filter itself is extremely powerful, allowing for ad-hoc custom filter chains to be executed based on any URL path expression.

First include the Shiro Spring web starter dependency in you application classpath (we recomend using a tool such as Apache Maven or Gradle to manage this).

++++
<@dependencies.dependencies anchorId="web" deps=[{"g":"org.apache.shiro", "a":"shiro-spring-boot-web-starter", "v":"${versions.latestRelease}"}] />
++++

Provide a Realm implementation:
[source,java]
----
@Bean
public Realm realm() {
  ...
}
----

And finally a `ShiroFilterChainDefinition` which will map any application specific paths to a given filter, in order to allow different paths different levels of access.

[source,java]
----
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();

    // logged in users with the 'admin' role
    chainDefinition.addPathDefinition("/admin/**", "authc, roles[admin]");

    // logged in users with the 'document:read' permission
    chainDefinition.addPathDefinition("/docs/**", "authc, perms[document:read]");

    // all other paths require a logged in user
    chainDefinition.addPathDefinition("/**", "authc");
    return chainDefinition;
}
----

If you are using Shiro's annotations see the link:#annotations_and_web_applications[annotation] section below.

You can see a full example in our link:https://github.com/apache/shiro/tree/main/samples/spring-boot-web[samples on Github].

=== Enabling Shiro Annotations

In both standalone and web applications, you might want to use Shiro's Annotations for security checks (for example, `@RequiresRoles`, `@RequiresPermissions`, etc.) These annotations are enabled automatically in both starters listed above.

Simply annotate your methods in order to use them:

[source,java]
----
@RequiresPermissions("document:read")
public void readDocument() {
    ...
}
----

=== Annotations and Web Applications

Shiro annotations are fully supported for use in `@Controller` classes, for example:

[source,java]
----
@Controller
public class AccountInfoController {

    @RequiresRoles("admin")
    @RequestMapping("/admin/config")
    public String adminConfig(Model model) {
        return "view";
    }
}
----

A `ShiroFilterChainDefinition` bean with at least one definition is still required for this to work, either configure all paths to be accessable via the `anon` filter or a filter in 'permissive' mode, for example: `authcBasic[permissive]`.

[source,java]
----
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
    chainDefinition.addPathDefinition("/**", "anon"); // all paths are managed via annotations

    // or allow basic authentication, but NOT require it.
    // chainDefinition.addPathDefinition("/**", "authcBasic[permissive]");
    return chainDefinition;
}
----

=== Caching

Enabling caching is as simple as providing a link:caching.html[CacheManager] bean:

[source,java]
----
@Bean
protected CacheManager cacheManager() {
    return new MemoryConstrainedCacheManager();
}
----

=== Configuration Properties

[width="100%",cols="36%,24%,40%",options="header",]
|===
|Key |Default Value |Description

|shiro.enabled
|`true`
|Enables Shiro’s Spring module

|shiro.web.enabled
|`true`
|Enables Shiro’s Spring web module

|shiro.annotations.enabled |`true` |Enables Spring support for Shiro’s annotations

|shiro.sessionManager.deleteInvalidSessions |`true` |Remove invalid session from session storage

|shiro.sessionManager.sessionIdCookieEnabled |`true` |Enable session ID to cookie, for session tracking

|shiro.sessionManager.sessionIdUrlRewritingEnabled |`true` |Enable session URL rewriting support

|shiro.userNativeSessionManager |`false` |If enabled Shiro will manage the HTTP sessions instead of the container

|shiro.sessionManager.cookie.name |`JSESSIONID` |Session cookie name

|shiro.sessionManager.cookie.maxAge |`-1` |Session cookie max age

|shiro.sessionManager.cookie.domain |null |Session cookie domain

|shiro.sessionManager.cookie.path |null |Session cookie path

|shiro.sessionManager.cookie.secure |`false` |Session cookie secure flag

|shiro.rememberMeManager.cookie.name |`rememberMe` |RememberMe cookie name

|shiro.rememberMeManager.cookie.maxAge |one year |RememberMe cookie max age

|shiro.rememberMeManager.cookie.domain |null |RememberMe cookie domain

|shiro.rememberMeManager.cookie.path |null |RememberMe cookie path

|shiro.rememberMeManager.cookie.secure |`false` |RememberMe cookie secure flag

|shiro.loginUrl |`/login.jsp` |Login URL used when unauthenticated users are redirected to login page

|shiro.successUrl |`/` |Default landing page after a user logs in (if alternative cannot be found in the current session)

|shiro.unauthorizedUrl |null |Page to redirect user to if they are unauthorized (403 page)
|===

== Standalone Applications

Include the Shiro Spring starter dependency in you application classpath (we recomend using a tool such as Apache Maven or Gradle to manage this).

++++
<@dependencies.dependencies anchorId="cli" deps=[{"g":"org.apache.shiro", "a":"shiro-spring-boot-starter", "v":"${versions.latestRelease}"}] />
++++

The only thing that is left is to configure a link:realm.html[realm]:

[source,java]
----
@Bean
public Realm realm() {
  ...
}
----

The easiest way to setup Shiro, so that all SecurityUtils.* methods work in all cases, is to make the `SecurityManager` bean a static singleton.  DO NOT do this in web applications - see the link:#web_applications[Web Applications] section below instead.

[source,java]
----
@Autowired
private SecurityManager securityManager;

 @PostConstruct
 private void initStaticSecurityManager() {
     SecurityUtils.setSecurityManager(securityManager);
 }
----

That is it, now you can get the current `Subject` using:

[source,java]
----
SecurityUtils.getSubject();
----

You can see a full example in our link:https://github.com/apache/shiro/tree/main/samples/spring-boot[samples on Github].
