0
# Authentication
1
2
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.
3
4
## Capabilities
5
6
### Authentication Tokens
7
8
Authentication tokens encapsulate user credentials for authentication attempts.
9
10
```java { .api }
11
/**
12
* An AuthenticationToken represents a user's principals and credentials to be submitted to an Authenticator.
13
*/
14
public interface AuthenticationToken extends Serializable {
15
/**
16
* Returns the account identity submitted during authentication.
17
* @return the account identity submitted during authentication
18
*/
19
Object getPrincipal();
20
21
/**
22
* Returns the credentials submitted by the user for authentication.
23
* @return the credentials submitted by the user for authentication
24
*/
25
Object getCredentials();
26
}
27
28
/**
29
* A HostAuthenticationToken retains the host information from where the authentication attempt occurs.
30
*/
31
public interface HostAuthenticationToken extends AuthenticationToken {
32
/**
33
* Returns the host name or IP string from where the authentication attempt occurs.
34
* @return the host name or IP string from where the authentication attempt occurs
35
*/
36
String getHost();
37
}
38
39
/**
40
* A RememberMeAuthenticationToken is a token that can indicate whether or not a user wishes their identity to be remembered.
41
*/
42
public interface RememberMeAuthenticationToken extends AuthenticationToken {
43
/**
44
* Returns true if the submitting user wishes their identity (principal(s)) to be remembered.
45
* @return true if the submitting user wishes their identity to be remembered
46
*/
47
boolean isRememberMe();
48
}
49
```
50
51
### Username Password Token
52
53
The most common authentication token implementation for username/password authentication.
54
55
```java { .api }
56
/**
57
* A simple username/password authentication token that supports remember-me functionality and host tracking.
58
*/
59
public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken {
60
/**
61
* Constructor accepting the username and password as char arrays.
62
* @param username the username submitted for authentication
63
* @param password the password submitted for authentication
64
*/
65
public UsernamePasswordToken(String username, char[] password);
66
67
/**
68
* Constructor accepting the username and password as strings.
69
* @param username the username submitted for authentication
70
* @param password the password submitted for authentication
71
*/
72
public UsernamePasswordToken(String username, String password);
73
74
/**
75
* Constructor accepting username, password, rememberMe, and host.
76
* @param username the username submitted for authentication
77
* @param password the password submitted for authentication
78
* @param rememberMe if the user wishes their identity to be remembered
79
* @param host the host name or IP from where the attempt is occurring
80
*/
81
public UsernamePasswordToken(String username, char[] password, boolean rememberMe, String host);
82
83
/**
84
* Returns the username submitted during authentication.
85
* @return the username submitted during authentication
86
*/
87
public String getUsername();
88
89
/**
90
* Returns the password submitted during authentication as a character array.
91
* @return the password submitted during authentication
92
*/
93
public char[] getPassword();
94
95
/**
96
* Sets whether or not the submitting user wishes their identity to be remembered.
97
* @param rememberMe whether or not the submitting user wishes their identity to be remembered
98
*/
99
public void setRememberMe(boolean rememberMe);
100
101
/**
102
* Sets the host name or IP where the authentication attempt is occurring.
103
* @param host the host name or IP where the authentication attempt is occurring
104
*/
105
public void setHost(String host);
106
107
/**
108
* Clears the password character array so the password cannot be inadvertently retained.
109
*/
110
public void clear();
111
}
112
```
113
114
**Usage Example:**
115
116
```java
117
// Basic username/password authentication
118
UsernamePasswordToken token = new UsernamePasswordToken("john.doe", "password123");
119
120
// With remember-me functionality
121
UsernamePasswordToken tokenWithRememberMe = new UsernamePasswordToken("john.doe", "password123");
122
tokenWithRememberMe.setRememberMe(true);
123
124
// With host tracking
125
UsernamePasswordToken tokenWithHost = new UsernamePasswordToken("john.doe", "password123", true, "192.168.1.100");
126
127
// Perform authentication
128
Subject currentUser = SecurityUtils.getSubject();
129
try {
130
currentUser.login(token);
131
System.out.println("Authentication successful");
132
} catch (AuthenticationException e) {
133
System.out.println("Authentication failed: " + e.getMessage());
134
} finally {
135
// Important: clear the token to prevent password exposure
136
token.clear();
137
}
138
```
139
140
### Authentication Info
141
142
Authentication information returned by realms after successful authentication.
143
144
```java { .api }
145
/**
146
* AuthenticationInfo represents a Subject's stored account information relevant to the authentication process.
147
*/
148
public interface AuthenticationInfo extends Serializable {
149
/**
150
* Returns all principals that identify the corresponding Subject.
151
* @return all principals that identify the corresponding Subject
152
*/
153
PrincipalCollection getPrincipals();
154
155
/**
156
* Returns the credentials associated with the corresponding Subject.
157
* @return the credentials associated with the corresponding Subject
158
*/
159
Object getCredentials();
160
}
161
162
/**
163
* Extended AuthenticationInfo that provides additional salt used for credential hashing.
164
*/
165
public interface SaltedAuthenticationInfo extends AuthenticationInfo {
166
/**
167
* Returns the salt used to hash the account's credentials.
168
* @return the salt used to hash the account's credentials
169
*/
170
ByteSource getCredentialsSalt();
171
}
172
173
/**
174
* MergableAuthenticationInfo allows multiple AuthenticationInfo objects to be merged together.
175
*/
176
public interface MergableAuthenticationInfo extends AuthenticationInfo {
177
/**
178
* Merges this instance's state with the specified AuthenticationInfo.
179
* @param info the AuthenticationInfo to merge into this instance
180
*/
181
void merge(AuthenticationInfo info);
182
}
183
184
/**
185
* Simple implementation of the AuthenticationInfo interface.
186
*/
187
public class SimpleAuthenticationInfo implements MergableAuthenticationInfo, SaltedAuthenticationInfo {
188
/**
189
* Constructor accepting a single principal and credentials.
190
* @param principal the identifying principal
191
* @param credentials the credentials that verify the principal
192
* @param realmName the realm name that verified the account
193
*/
194
public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName);
195
196
/**
197
* Constructor accepting principals, credentials, and salt.
198
* @param principals the identifying principals
199
* @param credentials the credentials that verify the principals
200
* @param credentialsSalt the salt used to hash the credentials
201
*/
202
public SimpleAuthenticationInfo(PrincipalCollection principals, Object credentials, ByteSource credentialsSalt);
203
204
public void merge(AuthenticationInfo info);
205
}
206
```
207
208
### Authenticator Interface
209
210
The core authentication coordination interface.
211
212
```java { .api }
213
/**
214
* An Authenticator is responsible for validating user identities based on credentials.
215
*/
216
public interface Authenticator {
217
/**
218
* Authenticates a user based on the submitted AuthenticationToken.
219
* @param authenticationToken the authentication token encapsulating user credentials
220
* @return account information associated with the authenticated user
221
* @throws AuthenticationException if authentication fails
222
*/
223
AuthenticationInfo authenticate(AuthenticationToken authenticationToken) throws AuthenticationException;
224
}
225
226
/**
227
* Abstract base class for Authenticator implementations that provides common caching functionality.
228
*/
229
public abstract class AbstractAuthenticator implements Authenticator, LogoutAware {
230
/**
231
* Template method for subclasses to implement specific authentication logic.
232
* @param token the authentication token
233
* @return authentication information for the authenticated account
234
* @throws AuthenticationException if authentication fails
235
*/
236
protected abstract AuthenticationInfo doAuthenticate(AuthenticationToken token) throws AuthenticationException;
237
238
public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException;
239
240
public void onLogout(PrincipalCollection principals);
241
}
242
243
/**
244
* Authenticator implementation that uses one or more configured realms to authenticate users.
245
*/
246
public class ModularRealmAuthenticator extends AbstractAuthenticator {
247
/**
248
* Sets the realms used by this Authenticator.
249
* @param realms the realms used by this Authenticator
250
*/
251
public void setRealms(Collection<Realm> realms);
252
253
/**
254
* Returns the realms used by this Authenticator.
255
* @return the realms used by this Authenticator
256
*/
257
public Collection<Realm> getRealms();
258
259
/**
260
* Sets the authentication strategy used when coordinating multiple realms.
261
* @param authenticationStrategy the authentication strategy
262
*/
263
public void setAuthenticationStrategy(AuthenticationStrategy authenticationStrategy);
264
265
/**
266
* Returns the authentication strategy used when coordinating multiple realms.
267
* @return the authentication strategy
268
*/
269
public AuthenticationStrategy getAuthenticationStrategy();
270
271
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException;
272
}
273
```
274
275
### Multi-Realm Authentication Strategies
276
277
Strategies for handling authentication across multiple realms.
278
279
```java { .api }
280
/**
281
* An AuthenticationStrategy coordinates authentication attempts across one or more configured realms.
282
*/
283
public interface AuthenticationStrategy {
284
/**
285
* Called before any realm authentication attempt.
286
* @param realms the realms configured for authentication
287
* @param token the authentication token submitted for authentication
288
* @return an aggregated AuthenticationInfo instance
289
* @throws AuthenticationException if the strategy determines authentication should fail immediately
290
*/
291
AuthenticationInfo beforeAllAttempts(Collection<Realm> realms, AuthenticationToken token) throws AuthenticationException;
292
293
/**
294
* Called before each individual realm authentication attempt.
295
* @param realm the realm about to be consulted
296
* @param token the authentication token submitted for authentication
297
* @param aggregate the aggregated AuthenticationInfo from previous realm consultation attempts
298
* @return the AuthenticationInfo object that should be consulted for account data
299
* @throws AuthenticationException if the strategy determines authentication should fail immediately
300
*/
301
AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;
302
303
/**
304
* Called after each individual realm authentication attempt.
305
* @param realm the realm that was consulted
306
* @param token the authentication token submitted for authentication
307
* @param singleRealmInfo the authentication information from the consulted realm
308
* @param aggregateInfo the aggregated authentication information
309
* @param t any exception thrown by the consulted realm
310
* @return the AuthenticationInfo object that will be presented to the next realm
311
* @throws AuthenticationException if the strategy determines authentication should fail immediately
312
*/
313
AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException;
314
315
/**
316
* Called after all realm authentication attempts.
317
* @param token the authentication token submitted for authentication
318
* @param aggregate the final aggregated AuthenticationInfo instance
319
* @return the final AuthenticationInfo instance that should be returned
320
* @throws AuthenticationException if the strategy determines authentication should fail
321
*/
322
AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;
323
}
324
325
/**
326
* Strategy requiring at least one realm to successfully authenticate.
327
*/
328
public class AtLeastOneSuccessfulStrategy extends AbstractAuthenticationStrategy {
329
public AtLeastOneSuccessfulStrategy();
330
}
331
332
/**
333
* Strategy requiring all configured realms to successfully authenticate.
334
*/
335
public class AllSuccessfulStrategy extends AbstractAuthenticationStrategy {
336
public AllSuccessfulStrategy();
337
}
338
339
/**
340
* Strategy that returns the first successful authentication attempt and ignores any further attempts.
341
*/
342
public class FirstSuccessfulStrategy extends AbstractAuthenticationStrategy {
343
public FirstSuccessfulStrategy();
344
}
345
```
346
347
**Usage Example:**
348
349
```java
350
// Configure multi-realm authentication
351
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
352
353
// Set up realms
354
Collection<Realm> realms = Arrays.asList(
355
new DatabaseRealm(),
356
new LdapRealm(),
357
new ActiveDirectoryRealm()
358
);
359
authenticator.setRealms(realms);
360
361
// Set authentication strategy
362
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
363
364
// Configure in security manager
365
DefaultSecurityManager securityManager = new DefaultSecurityManager();
366
securityManager.setAuthenticator(authenticator);
367
securityManager.setRealms(realms);
368
```
369
370
### Authentication Listeners
371
372
Listeners for authentication events.
373
374
```java { .api }
375
/**
376
* An AuthenticationListener listens for notifications while Subject authentication events occur.
377
*/
378
public interface AuthenticationListener {
379
/**
380
* Called immediately after a successful authentication.
381
* @param token the authentication token submitted during authentication
382
* @param info the authentication information returned after successful authentication
383
*/
384
void onSuccess(AuthenticationToken token, AuthenticationInfo info);
385
386
/**
387
* Called immediately after an unsuccessful authentication attempt.
388
* @param token the authentication token submitted during authentication
389
* @param ae the AuthenticationException that occurred as a result of the attempt
390
*/
391
void onFailure(AuthenticationToken token, AuthenticationException ae);
392
393
/**
394
* Called immediately after a Subject logs out.
395
* @param principals the identifying principals of the Subject being logged out
396
*/
397
void onLogout(PrincipalCollection principals);
398
}
399
400
/**
401
* Interface implemented by components that wish to be notified during logout.
402
*/
403
public interface LogoutAware {
404
/**
405
* Called when a Subject with the associated principals logs out.
406
* @param principals the identifying principals of the Subject logging out
407
*/
408
void onLogout(PrincipalCollection principals);
409
}
410
```
411
412
## Exception Hierarchy
413
414
```java { .api }
415
/**
416
* Base exception for all authentication-related problems.
417
*/
418
public class AuthenticationException extends ShiroException {
419
public AuthenticationException();
420
public AuthenticationException(String message);
421
public AuthenticationException(Throwable cause);
422
public AuthenticationException(String message, Throwable cause);
423
}
424
425
/**
426
* Base exception for all account-related authentication problems.
427
*/
428
public class AccountException extends AuthenticationException {
429
public AccountException();
430
public AccountException(String message);
431
public AccountException(Throwable cause);
432
public AccountException(String message, Throwable cause);
433
}
434
435
/**
436
* Thrown when attempting to authenticate with an unknown account (e.g. account doesn't exist).
437
*/
438
public class UnknownAccountException extends AccountException {
439
public UnknownAccountException();
440
public UnknownAccountException(String message);
441
public UnknownAccountException(Throwable cause);
442
public UnknownAccountException(String message, Throwable cause);
443
}
444
445
/**
446
* Thrown when submitted credentials are incorrect.
447
*/
448
public class IncorrectCredentialsException extends CredentialsException {
449
public IncorrectCredentialsException();
450
public IncorrectCredentialsException(String message);
451
public IncorrectCredentialsException(Throwable cause);
452
public IncorrectCredentialsException(String message, Throwable cause);
453
}
454
455
/**
456
* Exception thrown when attempting to authenticate with a locked account.
457
*/
458
public class LockedAccountException extends DisabledAccountException {
459
public LockedAccountException();
460
public LockedAccountException(String message);
461
public LockedAccountException(Throwable cause);
462
public LockedAccountException(String message, Throwable cause);
463
}
464
465
/**
466
* Exception thrown when too many authentication attempts have been made.
467
*/
468
public class ExcessiveAttemptsException extends AccountException {
469
public ExcessiveAttemptsException();
470
public ExcessiveAttemptsException(String message);
471
public ExcessiveAttemptsException(Throwable cause);
472
public ExcessiveAttemptsException(String message, Throwable cause);
473
}
474
475
/**
476
* Exception thrown when credentials have expired.
477
*/
478
public class ExpiredCredentialsException extends CredentialsException {
479
public ExpiredCredentialsException();
480
public ExpiredCredentialsException(String message);
481
public ExpiredCredentialsException(Throwable cause);
482
public ExpiredCredentialsException(String message, Throwable cause);
483
}
484
```