Search code examples
springspring-mvcshiro

Mapping Shiro exceptions at the service layer


I'm using Spring 3.2.3 and Shiro 1.2.0 to secure access to a service. This works, but results in throwing a Shiro-specific exception. I'd like to throw an application-specific exception instead. Is this possible, either with Shiro or mapping at the Spring level? I know I can map controller exceptions to views with Spring, but I'm not sure how to handle it at the service layer. My setup:

Service interface:

public interface CaseService {
  Case getCase(Integer id);
}

Service implementation:

@Service
public class CaseServiceImpl implements CaseService {
  @RequiresAuthentication
  public Case getCase(Integer id) {
    // ...
  }
}

When testing the above without an authenticated Subject, I do receive an exception as expected, but it is a org.apache.shiro.* one. I tried using Spring's @ExceptionHandler to handle the Shiro exception. It had no effect, but I think it needs to work at the controller layer.


Solution

  • If there isn't a reason you absolutely need use the @RequiresAuthentication annotation you can call the following custom utility class to return the exception you require.

    public class UserAuthenticationUtil {
      /**
       * Check that the current user bound to {@link ThreadLocal} is authenticated.
       * @throws ApplicationSpecificException If the current user is not authenticated.
       */
      public static void checkUserAuthenticated () throws ApplicationSpecificException {
        if (!SecurityUtils.getSubject().isAuthenticated()) {
          throw new ApplicationSpecificException("User is not authenticated!");
        }
      }
    }
    

    Here is the code/class that handles the @RequiresAuthentication annotation if you'd like to verify it is the same logic. Here is the API documenation as well.