title: Is an unbound SecurityManager really an invalid application configuration in Shiro?
body: <p>I'm adding Apache Shiro to my application and I'm wondering if the following error message is truly accurate:</p>
  
  <blockquote>
    <p>org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an invalid application configuration.</p>
  </blockquote>
  
  <p>I've looked through the source code a bit and the impression that I get is that as long as I'm not using <code>SecurityUtils</code> and I'm willing to pass a <code>SecurityManager</code> to components that need it, I don't actually need to assign the <code>SecurityManager</code> to the static singleton used by <code>SecurityUtils</code>.</p>
  
  <p>The specific thing I want to avoid is having Shiro put anything into <code>ThreadLocal</code> or having Shiro use its <code>ThreadContext</code> support class.  I'm using Apache Thrift and don't want to commit myself to a one-thread-per-request network design.  My requirements from Shiro are pretty minimal, so I'll show what I'm doing below.</p>
  
  <p>I'm using Guice in my application, but I'm <strong>not</strong> using <code>shiro-guice</code> because the Shiro AOP stuff depends on having a <code>Subject</code> associated with a <code>ThreadContext</code>.  Instead, I start with an extremely simple Guice module.</p>
  
  <pre class="lang-java prettyprint-override"><code>public class ShiroIniModule extends AbstractModule {
      @Override
      protected void configure() {}
  
      @Provides
      @Singleton
      public SecurityManager provideSecurityManager() {
          return new DefaultSecurityManager(new IniRealm("classpath:shiro.ini"));
      }
  }
  </code></pre>
  
  <p>That's not exactly a production quality realm / security manager setup, but it's good enough for me to test with.  Next, I create my own manager classes with a very limited scope that are used by the components of my application.  I have two of these; a <code>ThriftAuthenticationManager</code> and a <code>ThriftAuthorizationManager</code>.  Here is the former:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Singleton
  public class ThriftAuthenticationManager {
      private final Logger log = LoggerFactory.getLogger(ThriftAuthenticationManager.class);
  
      private final SecurityManager securityManager;
  
      @Inject
      public ThriftAuthenticationManager(SecurityManager securityManager) {
          this.securityManager = securityManager;
      }
  
      public String authenticate(String username, String password) throws TException {
          try {
              Subject currentUser = new Subject.Builder(securityManager).buildSubject();
  
              if (!currentUser.isAuthenticated()) {
                  currentUser.login(new UsernamePasswordToken(username, password));
              }
  
              String authToken = currentUser.getSession().getId().toString();
              Preconditions.checkState(!Strings.isNullOrEmpty(authToken));
              return authToken;
          }
          catch (AuthenticationException e) {
              throw Exceptions.security(SecurityExceptions.AUTHENTICATION_EXCEPTION);
          }
          catch(Throwable t) {
              log.error("Unexpected error during authentication.", t);
              throw new TException("Unexpected error during authentication.", t);
          }
  
      }
  }
  </code></pre>
  
  <p>And the latter:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Singleton
  public class ThriftAuthorizationManager {
      private final Logger log = LoggerFactory.getLogger(ThriftAuthorizationManager.class);
  
      private final SecurityManager securityManager;
  
      @Inject
      public ThriftAuthorizationManager(SecurityManager securityManager) {
          this.securityManager = securityManager;
      }
  
      public void checkPermissions(final String authToken, final String permissions)
              throws TException {
          withThriftExceptions(new Callable&lt;Void&gt;() {
              @Override
              public Void call() throws Exception {
                  securityManager.checkPermission(getPrincipals(authToken), permissions);
                  return null;
              }
          });
      }
  
      public void checkPermission(final String authToken, final Permission permission)
              throws TException {
          withThriftExceptions(new Callable&lt;Void&gt;() {
              @Override
              public Void call() throws Exception {
                  securityManager.checkPermission(getPrincipals(authToken), permission);
                  return null;
              }
          });
      }
  
      private Subject getSubject(String authToken) {
          return new Subject.Builder(securityManager).sessionId(authToken).buildSubject();
      }
  
      private PrincipalCollection getPrincipals(String authToken) {
          return getSubject(authToken).getPrincipals();
      }
  
      private void withThriftExceptions(Callable&lt;Void&gt; callable) throws TException {
          try {
              callable.call();
          }
          catch(SessionException e) {
              throw Exceptions.security(SecurityExceptions.SESSION_EXCEPTION);
          }
          catch(UnauthenticatedException e) {
              throw Exceptions.security(SecurityExceptions.UNAUTHENTICATED_EXCEPTION);
          }
          catch(AuthorizationException e) {
              throw Exceptions.security(SecurityExceptions.AUTHORIZATION_EXCEPTION);
          }
          catch(ShiroException e) {
              throw Exceptions.security(SecurityExceptions.SECURITY_EXCEPTION);
          }
          catch(Throwable t) {
              log.error("An unexpected error occurred during authorization.", t);
              throw new TException("Unexpected error during authorization.", t);
          }
      }
  }
  </code></pre>
  
  <p>My Thrift services use the above two classes for authentication and authorization.  For example:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Singleton
  public class EchoServiceImpl implements EchoService.Iface {
      private final Logger log = LoggerFactory.getLogger(EchoServiceImpl.class);
  
      private final ThriftAuthorizationManager authorizor;
  
      @Inject
      public EchoServiceImpl(ThriftAuthorizationManager authorizor) {
          this.authorizor = authorizor;
      }
  
      @Override
      public Echo echo(String authToken, Echo echo) throws TException {
          authorizor.checkPermissions(authToken, "echo");
          return echo;
      }
  }
  </code></pre>
  
  <p>So, I guess I actually have a few questsions.</p>
  
  <ol>
  <li><p>Is the error I quoted actually an error or just an overzealous log message?</p></li>
  <li><p>Do I need to worry about Shiro relying on anything in a <code>ThreadContext</code> if I never use <code>ShiroUtils</code>?</p></li>
  <li><p>Is there any harm in using <code>SecurityUtils#setSecurityManager</code> if I can't guarantee a one-thread-per-request environment?</p></li>
  <li><p>I haven't tried using Shiro's advanced permissions (<code>org.apache.shiro.authz.Permission</code>) yet.  Do they rely on anything in a <code>ThreadContext</code> or do anything weird that I should look into sooner than later?</p></li>
  <li><p>Have I done anything else that could cause me problems or could I improve anything?</p></li>
  </ol>