A powerful and flexible open-source Java security framework providing authentication, authorization, session management, and cryptographic services
—
Apache Shiro provides essential utility classes and interfaces for configuration, thread context management, lifecycle operations, and integration with various environments and frameworks. These utilities simplify common security operations and provide building blocks for custom integrations.
Central utility class providing static access to core Shiro functionality.
/**
* Utility class providing convenient static methods for accessing common security operations.
*/
public abstract class SecurityUtils {
/**
* Returns the currently executing Subject associated with the calling thread, or a new empty/anonymous Subject if none is associated.
* @return the Subject associated with the calling thread or a new empty/anonymous Subject if none is associated
*/
public static Subject getSubject();
/**
* Returns the SecurityManager accessible to the calling code.
* @return the SecurityManager accessible to the calling code
*/
public static SecurityManager getSecurityManager();
/**
* Sets the SecurityManager accessible to all threads.
* @param securityManager the SecurityManager to set
*/
public static void setSecurityManager(SecurityManager securityManager);
}Usage Examples:
// Get current user
Subject currentUser = SecurityUtils.getSubject();
// Check if user is authenticated
if (currentUser.isAuthenticated()) {
System.out.println("User is logged in");
}
// Get security manager
SecurityManager sm = SecurityUtils.getSecurityManager();
// Set security manager (typically done during application startup)
DefaultSecurityManager securityManager = new DefaultSecurityManager(realm);
SecurityUtils.setSecurityManager(securityManager);Utilities for managing security context in multi-threaded environments.
/**
* Utility class for managing security context in thread-local storage.
*/
public final class ThreadContext {
/**
* Returns the SecurityManager bound to the current thread, or null if none is bound.
* @return the SecurityManager bound to the current thread, or null if none is bound
*/
public static SecurityManager getSecurityManager();
/**
* Binds a SecurityManager to the current thread.
* @param securityManager the SecurityManager to bind to the current thread
*/
public static void bind(SecurityManager securityManager);
/**
* Unbinds the SecurityManager from the current thread.
* @return the SecurityManager previously bound to the current thread, or null if none was bound
*/
public static SecurityManager unbindSecurityManager();
/**
* Returns the Subject bound to the current thread, or null if none is bound.
* @return the Subject bound to the current thread, or null if none is bound
*/
public static Subject getSubject();
/**
* Binds a Subject to the current thread.
* @param subject the Subject to bind to the current thread
*/
public static void bind(Subject subject);
/**
* Unbinds the Subject from the current thread.
* @return the Subject previously bound to the current thread, or null if none was bound
*/
public static Subject unbindSubject();
/**
* Returns all resources bound to the current thread.
* @return all resources bound to the current thread as a Map
*/
public static Map<Object, Object> getResources();
/**
* Returns the resource bound to the current thread under the specified key.
* @param key the key used to lookup the resource
* @return the resource bound to the current thread under the specified key
*/
public static Object get(Object key);
/**
* Binds a resource to the current thread under the specified key.
* @param key the key to bind the resource under
* @param value the resource to bind
*/
public static void put(Object key, Object value);
/**
* Unbinds the resource associated with the specified key from the current thread.
* @param key the key of the resource to unbind
* @return the resource that was unbound, or null if no resource was bound under that key
*/
public static Object remove(Object key);
/**
* Removes all resources bound to the current thread.
*/
public static void clear();
}Usage Examples:
// Manual thread context management
public void executeInSecurityContext(Runnable task) {
Subject subject = SecurityUtils.getSubject();
try {
// Bind current subject to new thread
ThreadContext.bind(subject);
// Execute task with security context
task.run();
} finally {
// Always clean up thread context
ThreadContext.clear();
}
}
// Custom resource binding
ThreadContext.put("customKey", customObject);
Object retrieved = ThreadContext.get("customKey");
ThreadContext.remove("customKey");Interfaces and implementations for managing thread state across security contexts.
/**
* Interface for managing thread state that can be backed up and restored.
*/
public interface ThreadState {
/**
* Saves the current thread state and replaces it with the state represented by this instance.
*/
void bind();
/**
* Completely removes the state that was previously bound.
*/
void clear();
/**
* Restores the original thread state that existed before this instance's state was bound.
*/
void restore();
}
/**
* ThreadState implementation that manages Subject state for the current thread.
*/
public class SubjectThreadState implements ThreadState {
/**
* Constructor accepting the Subject that should be bound to the current thread.
* @param subject the Subject that should be bound to the current thread
*/
public SubjectThreadState(Subject subject);
/**
* Returns the Subject that will be bound to the current thread.
* @return the Subject that will be bound to the current thread
*/
public Subject getSubject();
public void bind();
public void clear();
public void restore();
}Usage Examples:
// Subject-aware thread execution
public void executeAsSubject(Subject subject, Runnable task) {
SubjectThreadState threadState = new SubjectThreadState(subject);
try {
threadState.bind();
task.run();
} finally {
threadState.restore();
}
}
// Custom thread state implementation
public class CustomThreadState implements ThreadState {
private final Map<String, Object> customState;
private Map<Object, Object> originalResources;
public CustomThreadState(Map<String, Object> state) {
this.customState = state;
}
@Override
public void bind() {
originalResources = ThreadContext.getResources();
customState.forEach(ThreadContext::put);
}
@Override
public void restore() {
ThreadContext.clear();
if (originalResources != null) {
originalResources.forEach(ThreadContext::put);
}
}
@Override
public void clear() {
ThreadContext.clear();
}
}Interfaces and utilities for component lifecycle management.
/**
* Interface implemented by components that need initialization.
*/
public interface Initializable {
/**
* Initializes this instance after all properties have been set.
* @throws ShiroException if initialization fails
*/
void init() throws ShiroException;
}
/**
* Interface implemented by components that need cleanup when destroyed.
*/
public interface Destroyable {
/**
* Destroys this instance, releasing any resources.
* @throws Exception if destruction fails
*/
void destroy() throws Exception;
}
/**
* Interface implemented by components that have names.
*/
public interface Nameable {
/**
* Sets the name of this component.
* @param name the name to assign to this component
*/
void setName(String name);
/**
* Returns the name assigned to this component.
* @return the name assigned to this component
*/
String getName();
}
/**
* Utility class for managing component lifecycles.
*/
public final class LifecycleUtils {
/**
* Initializes the specified object if it implements Initializable.
* @param o the object to initialize
* @throws ShiroException if initialization fails
*/
public static void init(Object o) throws ShiroException;
/**
* Initializes all objects in the specified collection.
* @param c the collection of objects to initialize
* @throws ShiroException if initialization of any object fails
*/
public static void init(Collection c) throws ShiroException;
/**
* Destroys the specified object if it implements Destroyable.
* @param o the object to destroy
*/
public static void destroy(Object o);
/**
* Destroys all objects in the specified collection.
* @param c the collection of objects to destroy
*/
public static void destroy(Collection c);
}Usage Examples:
// Custom component with lifecycle
public class MySecurityComponent implements Initializable, Destroyable, Nameable {
private String name;
private boolean initialized = false;
@Override
public void init() throws ShiroException {
if (initialized) {
return;
}
// Perform initialization
setupResources();
validateConfiguration();
initialized = true;
System.out.println("Component " + name + " initialized");
}
@Override
public void destroy() throws Exception {
if (!initialized) {
return;
}
// Cleanup resources
releaseResources();
initialized = false;
System.out.println("Component " + name + " destroyed");
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
private void setupResources() {
// Setup component resources
}
private void releaseResources() {
// Release component resources
}
private void validateConfiguration() throws ShiroException {
// Validate component configuration
if (name == null) {
throw new ShiroException("Component name must be specified");
}
}
}
// Using lifecycle utilities
List<Object> components = Arrays.asList(
new MySecurityComponent(),
new AnotherComponent(),
new YetAnotherComponent()
);
// Initialize all components
LifecycleUtils.init(components);
// Later, destroy all components
LifecycleUtils.destroy(components);Generic factory pattern support for component creation.
/**
* Generic factory interface for creating instances of type T.
* @param <T> the type of object created by this factory
*/
public interface Factory<T> {
/**
* Creates and returns a new instance of type T.
* @return a new instance of type T
*/
T getInstance();
}Usage Examples:
// Custom realm factory
public class DatabaseRealmFactory implements Factory<Realm> {
private DataSource dataSource;
public DatabaseRealmFactory(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Realm getInstance() {
JdbcRealm realm = new JdbcRealm();
realm.setDataSource(dataSource);
realm.setAuthenticationQuery("SELECT password FROM users WHERE username = ?");
realm.setUserRolesQuery("SELECT role FROM user_roles WHERE username = ?");
return realm;
}
}
// Security manager factory
public class SecurityManagerFactory implements Factory<SecurityManager> {
private final Collection<Realm> realms;
private final CacheManager cacheManager;
public SecurityManagerFactory(Collection<Realm> realms, CacheManager cacheManager) {
this.realms = realms;
this.cacheManager = cacheManager;
}
@Override
public SecurityManager getInstance() {
DefaultSecurityManager sm = new DefaultSecurityManager();
sm.setRealms(realms);
sm.setCacheManager(cacheManager);
return sm;
}
}
// Usage
Factory<Realm> realmFactory = new DatabaseRealmFactory(dataSource);
Realm realm = realmFactory.getInstance();
Factory<SecurityManager> smFactory = new SecurityManagerFactory(
Collections.singletonList(realm),
cacheManager
);
SecurityManager securityManager = smFactory.getInstance();Utility classes for common operations on strings and collections.
/**
* String manipulation utilities commonly used throughout Shiro.
*/
public final class StringUtils {
/**
* Returns true if the specified string is null or empty.
* @param str the string to check
* @return true if the string is null or empty, false otherwise
*/
public static boolean isEmpty(String str);
/**
* Returns true if the specified string has text (not null and not empty after trimming).
* @param str the string to check
* @return true if the string has text, false otherwise
*/
public static boolean hasText(String str);
/**
* Returns true if the specified string has length (not null and length > 0).
* @param str the string to check
* @return true if the string has length, false otherwise
*/
public static boolean hasLength(String str);
/**
* Cleans the specified string by removing leading and trailing whitespace.
* @param str the string to clean
* @return the cleaned string, or null if the input was null
*/
public static String clean(String str);
/**
* Splits the specified string using the specified delimiter.
* @param line the string to split
* @param delimiter the delimiter to use for splitting
* @return an array of tokens, or null if the input was null or empty
*/
public static String[] split(String line, String delimiter);
/**
* Tokenizes the specified string using the specified delimiters.
* @param str the string to tokenize
* @param delimiters the delimiters to use
* @return a list of tokens
*/
public static List<String> tokenizeToStringList(String str, String delimiters);
}
/**
* Collection manipulation utilities commonly used throughout Shiro.
*/
public final class CollectionUtils {
/**
* Returns true if the specified collection is null or empty.
* @param c the collection to check
* @return true if the collection is null or empty, false otherwise
*/
public static boolean isEmpty(Collection c);
/**
* Returns the size of the specified collection, or 0 if null.
* @param c the collection
* @return the size of the collection, or 0 if null
*/
public static int size(Collection c);
/**
* Returns true if the specified map is null or empty.
* @param m the map to check
* @return true if the map is null or empty, false otherwise
*/
public static boolean isEmpty(Map m);
/**
* Returns the size of the specified map, or 0 if null.
* @param m the map
* @return the size of the map, or 0 if null
*/
public static int size(Map m);
/**
* Converts the specified collection to a set.
* @param c the collection to convert
* @return a set containing the collection's elements
*/
public static Set asSet(Collection c);
}Usage Examples:
// String utilities
String username = " john.doe ";
if (StringUtils.hasText(username)) {
username = StringUtils.clean(username); // "john.doe"
}
String roles = "admin,user,guest";
String[] roleArray = StringUtils.split(roles, ","); // ["admin", "user", "guest"]
List<String> roleList = StringUtils.tokenizeToStringList(roles, ",");
// Collection utilities
Collection<String> permissions = getPermissions();
if (!CollectionUtils.isEmpty(permissions)) {
System.out.println("User has " + CollectionUtils.size(permissions) + " permissions");
}
Set<String> uniqueRoles = CollectionUtils.asSet(roleList);Utilities for class loading and reflection operations.
/**
* Class loading and reflection utilities.
*/
public final class ClassUtils {
/**
* Returns the thread context class loader, or the system class loader if the context loader is null.
* @return the thread context class loader, or the system class loader if the context loader is null
*/
public static ClassLoader getDefaultClassLoader();
/**
* Loads the class with the specified name using the default class loader.
* @param className the name of the class to load
* @return the loaded class
* @throws ClassNotFoundException if the class cannot be found
*/
public static Class forName(String className) throws ClassNotFoundException;
/**
* Loads the class with the specified name using the specified class loader.
* @param className the name of the class to load
* @param classLoader the class loader to use
* @return the loaded class
* @throws ClassNotFoundException if the class cannot be found
*/
public static Class forName(String className, ClassLoader classLoader) throws ClassNotFoundException;
/**
* Instantiates the class with the specified name using its default constructor.
* @param className the name of the class to instantiate
* @return a new instance of the specified class
* @throws InstantiationException if the class cannot be instantiated
* @throws IllegalAccessException if the constructor is not accessible
* @throws ClassNotFoundException if the class cannot be found
*/
public static Object newInstance(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException;
/**
* Instantiates the specified class using its default constructor.
* @param clazz the class to instantiate
* @return a new instance of the specified class
* @throws InstantiationException if the class cannot be instantiated
* @throws IllegalAccessException if the constructor is not accessible
*/
public static Object newInstance(Class clazz) throws InstantiationException, IllegalAccessException;
/**
* Returns true if the specified class is available in the classpath.
* @param className the name of the class to check
* @return true if the class is available, false otherwise
*/
public static boolean isAvailable(String className);
}Usage Examples:
// Dynamic class loading
if (ClassUtils.isAvailable("com.company.CustomRealm")) {
try {
Class<?> realmClass = ClassUtils.forName("com.company.CustomRealm");
Realm customRealm = (Realm) ClassUtils.newInstance(realmClass);
// Use the dynamically loaded realm
securityManager.setRealm(customRealm);
} catch (Exception e) {
System.err.println("Failed to load custom realm: " + e.getMessage());
}
}
// Get default class loader
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
// Load class with specific class loader
Class<?> myClass = ClassUtils.forName("com.example.MyClass", classLoader);
Object instance = ClassUtils.newInstance(myClass);Utilities for executing tasks with Shiro security context in multi-threaded environments.
/**
* Executor that automatically associates Subject instances with executing threads.
*/
public class SubjectAwareExecutor implements Executor {
/**
* Constructor accepting the target Executor that will actually execute the commands.
* @param targetExecutor the target Executor that will actually execute the commands
*/
public SubjectAwareExecutor(Executor targetExecutor);
/**
* Executes the specified command with the current Subject automatically associated with the executing thread.
* @param command the command to execute
*/
public void execute(Runnable command);
}
/**
* ExecutorService that automatically associates Subject instances with executing threads.
*/
public class SubjectAwareExecutorService extends AbstractExecutorService {
/**
* Constructor accepting the target ExecutorService that will actually execute the commands.
* @param targetExecutorService the target ExecutorService that will actually execute the commands
*/
public SubjectAwareExecutorService(ExecutorService targetExecutorService);
/**
* Returns the target ExecutorService that actually executes the commands.
* @return the target ExecutorService that actually executes the commands
*/
public ExecutorService getTargetExecutorService();
public void execute(Runnable command);
public <T> Future<T> submit(Callable<T> task);
public <T> Future<T> submit(Runnable task, T result);
public Future<?> submit(Runnable task);
}Usage Examples:
// Subject-aware executor
Subject currentUser = SecurityUtils.getSubject();
Executor standardExecutor = Executors.newFixedThreadPool(10);
SubjectAwareExecutor subjectAwareExecutor = new SubjectAwareExecutor(standardExecutor);
// Execute task with subject context
subjectAwareExecutor.execute(() -> {
// This code runs with the current user's security context
Subject subject = SecurityUtils.getSubject();
if (subject.hasRole("admin")) {
performAdminTask();
}
});
// Subject-aware executor service
ExecutorService standardService = Executors.newCachedThreadPool();
SubjectAwareExecutorService subjectAwareService = new SubjectAwareExecutorService(standardService);
// Submit callable with subject context
Future<String> result = subjectAwareService.submit(() -> {
Subject subject = SecurityUtils.getSubject();
return "Task completed by user: " + subject.getPrincipal();
});
try {
String message = result.get();
System.out.println(message);
} catch (Exception e) {
e.printStackTrace();
}Interface for components that need to be aware of the cache manager.
/**
* Interface implemented by components that can be configured with a CacheManager.
*/
public interface CacheManagerAware {
/**
* Sets the CacheManager that should be used for caching.
* @param cacheManager the CacheManager to use for caching
*/
void setCacheManager(CacheManager cacheManager);
}These utilities form the foundation for building robust, secure applications with Apache Shiro, providing essential functionality for security context management, component lifecycle, and multi-threaded execution with proper security context propagation.
Install with Tessl CLI
npx tessl i tessl/maven-org-apache-shiro--shiro-core