@Override
  public Subject getSubject() {
    Subject currentUser;

    // First try get the principal out of AccessControlContext instead of Shiro's Thread context
    // since threads can be shared between JMX clients.
    javax.security.auth.Subject jmxSubject =
        javax.security.auth.Subject.getSubject(AccessController.getContext());

    if (jmxSubject != null) {
      Set<ShiroPrincipal> principals = jmxSubject.getPrincipals(ShiroPrincipal.class);
      if (!principals.isEmpty()) {
        ShiroPrincipal principal = principals.iterator().next();
        currentUser = principal.getSubject();
        ThreadContext.bind(currentUser);
        return currentUser;
      }
    }

    try {
      // in other cases like rest call, client operations, we get it from the current thread
      currentUser = getCurrentUser();
    } catch (UnavailableSecurityManagerException e) {
      throw new CacheClosedException("Cache is closed.", e);
    }

    if (currentUser == null || currentUser.getPrincipal() == null) {
      throw new AuthenticationRequiredException("Failed to find the authenticated user.");
    }

    return currentUser;
  }
It first looks the shiro subject in AccessControlContext since JMX will use multiple threads to
process operations from the same client, then it looks into Shiro's thead context.

@return the shiro subject, null if security is not enabled
geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java