A powerful and flexible open-source Java security framework providing authentication, authorization, session management, and cryptographic services
—
Apache Shiro's authentication framework provides comprehensive identity verification capabilities with support for multiple authentication mechanisms, credential matching strategies, and multi-realm authentication. The framework is designed to be flexible and extensible while providing secure defaults.
Authentication tokens encapsulate user credentials for authentication attempts.
/**
* An AuthenticationToken represents a user's principals and credentials to be submitted to an Authenticator.
*/
public interface AuthenticationToken extends Serializable {
/**
* Returns the account identity submitted during authentication.
* @return the account identity submitted during authentication
*/
Object getPrincipal();
/**
* Returns the credentials submitted by the user for authentication.
* @return the credentials submitted by the user for authentication
*/
Object getCredentials();
}
/**
* A HostAuthenticationToken retains the host information from where the authentication attempt occurs.
*/
public interface HostAuthenticationToken extends AuthenticationToken {
/**
* Returns the host name or IP string from where the authentication attempt occurs.
* @return the host name or IP string from where the authentication attempt occurs
*/
String getHost();
}
/**
* A RememberMeAuthenticationToken is a token that can indicate whether or not a user wishes their identity to be remembered.
*/
public interface RememberMeAuthenticationToken extends AuthenticationToken {
/**
* Returns true if the submitting user wishes their identity (principal(s)) to be remembered.
* @return true if the submitting user wishes their identity to be remembered
*/
boolean isRememberMe();
}The most common authentication token implementation for username/password authentication.
/**
* A simple username/password authentication token that supports remember-me functionality and host tracking.
*/
public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken {
/**
* Constructor accepting the username and password as char arrays.
* @param username the username submitted for authentication
* @param password the password submitted for authentication
*/
public UsernamePasswordToken(String username, char[] password);
/**
* Constructor accepting the username and password as strings.
* @param username the username submitted for authentication
* @param password the password submitted for authentication
*/
public UsernamePasswordToken(String username, String password);
/**
* Constructor accepting username, password, rememberMe, and host.
* @param username the username submitted for authentication
* @param password the password submitted for authentication
* @param rememberMe if the user wishes their identity to be remembered
* @param host the host name or IP from where the attempt is occurring
*/
public UsernamePasswordToken(String username, char[] password, boolean rememberMe, String host);
/**
* Returns the username submitted during authentication.
* @return the username submitted during authentication
*/
public String getUsername();
/**
* Returns the password submitted during authentication as a character array.
* @return the password submitted during authentication
*/
public char[] getPassword();
/**
* Sets whether or not the submitting user wishes their identity to be remembered.
* @param rememberMe whether or not the submitting user wishes their identity to be remembered
*/
public void setRememberMe(boolean rememberMe);
/**
* Sets the host name or IP where the authentication attempt is occurring.
* @param host the host name or IP where the authentication attempt is occurring
*/
public void setHost(String host);
/**
* Clears the password character array so the password cannot be inadvertently retained.
*/
public void clear();
}Usage Example:
// Basic username/password authentication
UsernamePasswordToken token = new UsernamePasswordToken("john.doe", "password123");
// With remember-me functionality
UsernamePasswordToken tokenWithRememberMe = new UsernamePasswordToken("john.doe", "password123");
tokenWithRememberMe.setRememberMe(true);
// With host tracking
UsernamePasswordToken tokenWithHost = new UsernamePasswordToken("john.doe", "password123", true, "192.168.1.100");
// Perform authentication
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.login(token);
System.out.println("Authentication successful");
} catch (AuthenticationException e) {
System.out.println("Authentication failed: " + e.getMessage());
} finally {
// Important: clear the token to prevent password exposure
token.clear();
}Authentication information returned by realms after successful authentication.
/**
* AuthenticationInfo represents a Subject's stored account information relevant to the authentication process.
*/
public interface AuthenticationInfo extends Serializable {
/**
* Returns all principals that identify the corresponding Subject.
* @return all principals that identify the corresponding Subject
*/
PrincipalCollection getPrincipals();
/**
* Returns the credentials associated with the corresponding Subject.
* @return the credentials associated with the corresponding Subject
*/
Object getCredentials();
}
/**
* Extended AuthenticationInfo that provides additional salt used for credential hashing.
*/
public interface SaltedAuthenticationInfo extends AuthenticationInfo {
/**
* Returns the salt used to hash the account's credentials.
* @return the salt used to hash the account's credentials
*/
ByteSource getCredentialsSalt();
}
/**
* MergableAuthenticationInfo allows multiple AuthenticationInfo objects to be merged together.
*/
public interface MergableAuthenticationInfo extends AuthenticationInfo {
/**
* Merges this instance's state with the specified AuthenticationInfo.
* @param info the AuthenticationInfo to merge into this instance
*/
void merge(AuthenticationInfo info);
}
/**
* Simple implementation of the AuthenticationInfo interface.
*/
public class SimpleAuthenticationInfo implements MergableAuthenticationInfo, SaltedAuthenticationInfo {
/**
* Constructor accepting a single principal and credentials.
* @param principal the identifying principal
* @param credentials the credentials that verify the principal
* @param realmName the realm name that verified the account
*/
public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName);
/**
* Constructor accepting principals, credentials, and salt.
* @param principals the identifying principals
* @param credentials the credentials that verify the principals
* @param credentialsSalt the salt used to hash the credentials
*/
public SimpleAuthenticationInfo(PrincipalCollection principals, Object credentials, ByteSource credentialsSalt);
public void merge(AuthenticationInfo info);
}The core authentication coordination interface.
/**
* An Authenticator is responsible for validating user identities based on credentials.
*/
public interface Authenticator {
/**
* Authenticates a user based on the submitted AuthenticationToken.
* @param authenticationToken the authentication token encapsulating user credentials
* @return account information associated with the authenticated user
* @throws AuthenticationException if authentication fails
*/
AuthenticationInfo authenticate(AuthenticationToken authenticationToken) throws AuthenticationException;
}
/**
* Abstract base class for Authenticator implementations that provides common caching functionality.
*/
public abstract class AbstractAuthenticator implements Authenticator, LogoutAware {
/**
* Template method for subclasses to implement specific authentication logic.
* @param token the authentication token
* @return authentication information for the authenticated account
* @throws AuthenticationException if authentication fails
*/
protected abstract AuthenticationInfo doAuthenticate(AuthenticationToken token) throws AuthenticationException;
public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException;
public void onLogout(PrincipalCollection principals);
}
/**
* Authenticator implementation that uses one or more configured realms to authenticate users.
*/
public class ModularRealmAuthenticator extends AbstractAuthenticator {
/**
* Sets the realms used by this Authenticator.
* @param realms the realms used by this Authenticator
*/
public void setRealms(Collection<Realm> realms);
/**
* Returns the realms used by this Authenticator.
* @return the realms used by this Authenticator
*/
public Collection<Realm> getRealms();
/**
* Sets the authentication strategy used when coordinating multiple realms.
* @param authenticationStrategy the authentication strategy
*/
public void setAuthenticationStrategy(AuthenticationStrategy authenticationStrategy);
/**
* Returns the authentication strategy used when coordinating multiple realms.
* @return the authentication strategy
*/
public AuthenticationStrategy getAuthenticationStrategy();
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException;
}Strategies for handling authentication across multiple realms.
/**
* An AuthenticationStrategy coordinates authentication attempts across one or more configured realms.
*/
public interface AuthenticationStrategy {
/**
* Called before any realm authentication attempt.
* @param realms the realms configured for authentication
* @param token the authentication token submitted for authentication
* @return an aggregated AuthenticationInfo instance
* @throws AuthenticationException if the strategy determines authentication should fail immediately
*/
AuthenticationInfo beforeAllAttempts(Collection<Realm> realms, AuthenticationToken token) throws AuthenticationException;
/**
* Called before each individual realm authentication attempt.
* @param realm the realm about to be consulted
* @param token the authentication token submitted for authentication
* @param aggregate the aggregated AuthenticationInfo from previous realm consultation attempts
* @return the AuthenticationInfo object that should be consulted for account data
* @throws AuthenticationException if the strategy determines authentication should fail immediately
*/
AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;
/**
* Called after each individual realm authentication attempt.
* @param realm the realm that was consulted
* @param token the authentication token submitted for authentication
* @param singleRealmInfo the authentication information from the consulted realm
* @param aggregateInfo the aggregated authentication information
* @param t any exception thrown by the consulted realm
* @return the AuthenticationInfo object that will be presented to the next realm
* @throws AuthenticationException if the strategy determines authentication should fail immediately
*/
AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException;
/**
* Called after all realm authentication attempts.
* @param token the authentication token submitted for authentication
* @param aggregate the final aggregated AuthenticationInfo instance
* @return the final AuthenticationInfo instance that should be returned
* @throws AuthenticationException if the strategy determines authentication should fail
*/
AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;
}
/**
* Strategy requiring at least one realm to successfully authenticate.
*/
public class AtLeastOneSuccessfulStrategy extends AbstractAuthenticationStrategy {
public AtLeastOneSuccessfulStrategy();
}
/**
* Strategy requiring all configured realms to successfully authenticate.
*/
public class AllSuccessfulStrategy extends AbstractAuthenticationStrategy {
public AllSuccessfulStrategy();
}
/**
* Strategy that returns the first successful authentication attempt and ignores any further attempts.
*/
public class FirstSuccessfulStrategy extends AbstractAuthenticationStrategy {
public FirstSuccessfulStrategy();
}Usage Example:
// Configure multi-realm authentication
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
// Set up realms
Collection<Realm> realms = Arrays.asList(
new DatabaseRealm(),
new LdapRealm(),
new ActiveDirectoryRealm()
);
authenticator.setRealms(realms);
// Set authentication strategy
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
// Configure in security manager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setAuthenticator(authenticator);
securityManager.setRealms(realms);Listeners for authentication events.
/**
* An AuthenticationListener listens for notifications while Subject authentication events occur.
*/
public interface AuthenticationListener {
/**
* Called immediately after a successful authentication.
* @param token the authentication token submitted during authentication
* @param info the authentication information returned after successful authentication
*/
void onSuccess(AuthenticationToken token, AuthenticationInfo info);
/**
* Called immediately after an unsuccessful authentication attempt.
* @param token the authentication token submitted during authentication
* @param ae the AuthenticationException that occurred as a result of the attempt
*/
void onFailure(AuthenticationToken token, AuthenticationException ae);
/**
* Called immediately after a Subject logs out.
* @param principals the identifying principals of the Subject being logged out
*/
void onLogout(PrincipalCollection principals);
}
/**
* Interface implemented by components that wish to be notified during logout.
*/
public interface LogoutAware {
/**
* Called when a Subject with the associated principals logs out.
* @param principals the identifying principals of the Subject logging out
*/
void onLogout(PrincipalCollection principals);
}/**
* Base exception for all authentication-related problems.
*/
public class AuthenticationException extends ShiroException {
public AuthenticationException();
public AuthenticationException(String message);
public AuthenticationException(Throwable cause);
public AuthenticationException(String message, Throwable cause);
}
/**
* Base exception for all account-related authentication problems.
*/
public class AccountException extends AuthenticationException {
public AccountException();
public AccountException(String message);
public AccountException(Throwable cause);
public AccountException(String message, Throwable cause);
}
/**
* Thrown when attempting to authenticate with an unknown account (e.g. account doesn't exist).
*/
public class UnknownAccountException extends AccountException {
public UnknownAccountException();
public UnknownAccountException(String message);
public UnknownAccountException(Throwable cause);
public UnknownAccountException(String message, Throwable cause);
}
/**
* Thrown when submitted credentials are incorrect.
*/
public class IncorrectCredentialsException extends CredentialsException {
public IncorrectCredentialsException();
public IncorrectCredentialsException(String message);
public IncorrectCredentialsException(Throwable cause);
public IncorrectCredentialsException(String message, Throwable cause);
}
/**
* Exception thrown when attempting to authenticate with a locked account.
*/
public class LockedAccountException extends DisabledAccountException {
public LockedAccountException();
public LockedAccountException(String message);
public LockedAccountException(Throwable cause);
public LockedAccountException(String message, Throwable cause);
}
/**
* Exception thrown when too many authentication attempts have been made.
*/
public class ExcessiveAttemptsException extends AccountException {
public ExcessiveAttemptsException();
public ExcessiveAttemptsException(String message);
public ExcessiveAttemptsException(Throwable cause);
public ExcessiveAttemptsException(String message, Throwable cause);
}
/**
* Exception thrown when credentials have expired.
*/
public class ExpiredCredentialsException extends CredentialsException {
public ExpiredCredentialsException();
public ExpiredCredentialsException(String message);
public ExpiredCredentialsException(Throwable cause);
public ExpiredCredentialsException(String message, Throwable cause);
}Install with Tessl CLI
npx tessl i tessl/maven-org-apache-shiro--shiro-core