0
# Authentication and Security
1
2
Comprehensive authentication and authorization framework including BASIC, DIGEST, FORM, and CLIENT-CERT authenticators, realm implementations for user/role management, credential handlers for password encryption, and Jakarta Authentication (JASPIC) integration for custom authentication modules.
3
4
## Capabilities
5
6
### Realm Interface
7
8
Core authentication and authorization interface.
9
10
```java { .api }
11
public interface Realm {
12
// Container
13
Container getContainer();
14
void setContainer(Container container);
15
16
// Credential handler
17
CredentialHandler getCredentialHandler();
18
void setCredentialHandler(CredentialHandler credentialHandler);
19
20
// Authentication methods
21
Principal authenticate(String username);
22
Principal authenticate(String username, String credentials);
23
Principal authenticate(String username, String digest, String nonce, String nc,
24
String cnonce, String qop, String realm, String digestA2);
25
Principal authenticate(String username, String digest, String nonce, String nc,
26
String cnonce, String qop, String realm, String digestA2, String algorithm);
27
Principal authenticate(GSSContext gssContext, boolean storeCreds);
28
Principal authenticate(GSSName gssName, GSSCredential gssCredential);
29
Principal authenticate(X509Certificate[] certs);
30
31
// Authorization
32
boolean hasRole(Wrapper wrapper, Principal principal, String role);
33
boolean hasResourcePermission(Request request, Response response,
34
SecurityConstraint[] constraints, Context context) throws IOException;
35
boolean hasUserDataPermission(Request request, Response response,
36
SecurityConstraint[] constraints) throws IOException;
37
38
// Background processing
39
void backgroundProcess();
40
41
// Security constraints
42
SecurityConstraint[] findSecurityConstraints(Request request, Context context);
43
44
// Event listeners
45
void addPropertyChangeListener(PropertyChangeListener listener);
46
void removePropertyChangeListener(PropertyChangeListener listener);
47
}
48
```
49
50
### Realm Implementations
51
52
Tomcat provides multiple concrete realm implementations for different user storage backends.
53
54
```java { .api }
55
/**
56
* Base class for Realm implementations providing common functionality.
57
*/
58
public abstract class RealmBase implements Realm, Lifecycle {
59
protected Container container;
60
protected CredentialHandler credentialHandler;
61
62
// Subclasses must implement these methods
63
protected abstract String getPassword(String username);
64
protected abstract Principal getPrincipal(String username);
65
public abstract boolean hasRole(Wrapper wrapper, Principal principal, String role);
66
}
67
68
/**
69
* Simple in-memory realm for development and testing.
70
* Users and roles are defined in tomcat-users.xml.
71
*/
72
public class MemoryRealm extends RealmBase {
73
public MemoryRealm();
74
75
/** Set path to the users configuration file */
76
public void setPathname(String pathname);
77
public String getPathname();
78
}
79
80
/**
81
* Realm implementation that reads user information from a JDBC database.
82
*/
83
public class DataSourceRealm extends RealmBase {
84
public DataSourceRealm();
85
86
/** Set the JNDI name of the DataSource */
87
public void setDataSourceName(String dataSourceName);
88
public String getDataSourceName();
89
90
/** Set the SQL query to retrieve user credentials */
91
public void setUserCredCol(String userCredCol);
92
public String getUserCredCol();
93
94
/** Set the SQL query to retrieve user roles */
95
public void setUserRoleTable(String userRoleTable);
96
public String getUserRoleTable();
97
98
/** Set the name column in user table */
99
public void setUserNameCol(String userNameCol);
100
public String getUserNameCol();
101
102
/** Set the name of the user table */
103
public void setUserTable(String userTable);
104
public String getUserTable();
105
106
/** Set the role name column */
107
public void setRoleNameCol(String roleNameCol);
108
public String getRoleNameCol();
109
}
110
111
/**
112
* Realm implementation that authenticates users against an LDAP directory.
113
*/
114
public class JNDIRealm extends RealmBase {
115
public JNDIRealm();
116
117
/** Set the connection URL for the LDAP server */
118
public void setConnectionURL(String connectionURL);
119
public String getConnectionURL();
120
121
/** Set the connection name (DN) to use for authentication */
122
public void setConnectionName(String connectionName);
123
public String getConnectionName();
124
125
/** Set the connection password */
126
public void setConnectionPassword(String connectionPassword);
127
128
/** Set the base DN for user searches */
129
public void setUserBase(String userBase);
130
public String getUserBase();
131
132
/** Set the search pattern for finding users */
133
public void setUserSearch(String userSearch);
134
public String getUserSearch();
135
136
/** Set the base DN for role searches */
137
public void setRoleBase(String roleBase);
138
public String getRoleBase();
139
140
/** Set the search pattern for finding roles */
141
public void setRoleSearch(String roleSearch);
142
public String getRoleSearch();
143
144
/** Set the attribute name for role names */
145
public void setRoleName(String roleName);
146
public String getRoleName();
147
148
/** Set whether to use subtree scope for searches */
149
public void setRoleSubtree(boolean roleSubtree);
150
public boolean getRoleSubtree();
151
152
/** Set whether nested groups should be searched */
153
public void setRoleNested(boolean roleNested);
154
public boolean getRoleNested();
155
}
156
157
/**
158
* Realm implementation that uses JAAS for authentication.
159
*/
160
public class JAASRealm extends RealmBase {
161
public JAASRealm();
162
163
/** Set the JAAS application name */
164
public void setAppName(String appName);
165
public String getAppName();
166
167
/** Set the user class name */
168
public void setUserClassNames(String userClassNames);
169
public String getUserClassNames();
170
171
/** Set the role class names */
172
public void setRoleClassNames(String roleClassNames);
173
public String getRoleClassNames();
174
175
/** Set whether to use context class loader */
176
public void setUseContextClassLoader(boolean useContextClassLoader);
177
public boolean isUseContextClassLoader();
178
}
179
180
/**
181
* Realm implementation that uses the UserDatabase JNDI resource.
182
*/
183
public class UserDatabaseRealm extends RealmBase {
184
public UserDatabaseRealm();
185
186
/** Set the JNDI name of the UserDatabase resource */
187
public void setResourceName(String resourceName);
188
public String getResourceName();
189
}
190
191
/**
192
* Realm that combines multiple realms for authentication.
193
* Attempts authentication against each realm in sequence.
194
*/
195
public class CombinedRealm extends RealmBase {
196
public CombinedRealm();
197
198
/** Add a realm to the combined realm */
199
public void addRealm(Realm realm);
200
201
/** Get all configured realms */
202
public Realm[] getNestedRealms();
203
}
204
205
/**
206
* Realm that provides brute force attack protection by locking out users
207
* after too many failed authentication attempts.
208
*/
209
public class LockOutRealm extends CombinedRealm {
210
public LockOutRealm();
211
212
/** Set the number of failed attempts before lockout */
213
public void setFailureCount(int failureCount);
214
public int getFailureCount();
215
216
/** Set the lockout duration in seconds */
217
public void setLockOutTime(int lockOutTime);
218
public int getLockOutTime();
219
220
/** Set the time window for counting failures in seconds */
221
public void setCacheSize(int cacheSize);
222
public int getCacheSize();
223
224
/** Set whether to cache authenticated users */
225
public void setCacheRemovalWarningTime(int cacheRemovalWarningTime);
226
public int getCacheRemovalWarningTime();
227
}
228
229
/**
230
* No-op realm that always denies authentication.
231
* Useful for applications that don't require authentication.
232
*/
233
public class NullRealm extends RealmBase {
234
public NullRealm();
235
}
236
```
237
238
### Credential Handler
239
240
Credential handler implementations for password encryption and verification.
241
242
```java { .api }
243
/**
244
* Base credential handler interface.
245
*/
246
public interface CredentialHandler {
247
boolean matches(String inputCredentials, String storedCredentials);
248
String mutate(String inputCredentials);
249
}
250
251
/**
252
* Credential handler using message digest algorithms (MD5, SHA-256, etc.).
253
*/
254
public class MessageDigestCredentialHandler implements CredentialHandler {
255
public MessageDigestCredentialHandler();
256
257
/** Set the digest algorithm (e.g., "SHA-256", "MD5") */
258
public void setAlgorithm(String algorithm);
259
public String getAlgorithm();
260
261
/** Set the digest encoding ("hex" or "base64") */
262
public void setEncoding(String encoding);
263
public String getEncoding();
264
265
/** Set the number of iterations for key derivation */
266
public void setIterations(int iterations);
267
public int getIterations();
268
269
/** Set the salt length in bytes */
270
public void setSaltLength(int saltLength);
271
public int getSaltLength();
272
273
@Override
274
public boolean matches(String inputCredentials, String storedCredentials);
275
276
@Override
277
public String mutate(String inputCredentials);
278
}
279
280
/**
281
* Credential handler using SecretKeyFactory for PBKDF2 and similar algorithms.
282
*/
283
public class SecretKeyCredentialHandler implements CredentialHandler {
284
public SecretKeyCredentialHandler();
285
286
/** Set the algorithm (e.g., "PBKDF2WithHmacSHA256") */
287
public void setAlgorithm(String algorithm);
288
public String getAlgorithm();
289
290
/** Set the number of iterations */
291
public void setIterations(int iterations);
292
public int getIterations();
293
294
/** Set the key length in bits */
295
public void setKeyLength(int keyLength);
296
public int getKeyLength();
297
298
/** Set the salt length in bytes */
299
public void setSaltLength(int saltLength);
300
public int getSaltLength();
301
302
@Override
303
public boolean matches(String inputCredentials, String storedCredentials);
304
305
@Override
306
public String mutate(String inputCredentials);
307
}
308
309
/**
310
* Credential handler that supports multiple nested credential handlers.
311
* Tries each handler in sequence for matching.
312
*/
313
public class NestedCredentialHandler implements CredentialHandler {
314
public NestedCredentialHandler();
315
316
/** Add a credential handler */
317
public void addCredentialHandler(CredentialHandler handler);
318
319
/** Get all configured credential handlers */
320
public CredentialHandler[] getCredentialHandlers();
321
322
@Override
323
public boolean matches(String inputCredentials, String storedCredentials);
324
325
@Override
326
public String mutate(String inputCredentials);
327
}
328
```
329
330
**Configuration Example:**
331
332
```java
333
import org.apache.catalina.realm.DataSourceRealm;
334
import org.apache.catalina.realm.MessageDigestCredentialHandler;
335
336
// Configure DataSource realm with SHA-256 password hashing
337
DataSourceRealm realm = new DataSourceRealm();
338
realm.setDataSourceName("java:comp/env/jdbc/UserDB");
339
realm.setUserTable("users");
340
realm.setUserNameCol("username");
341
realm.setUserCredCol("password");
342
realm.setUserRoleTable("user_roles");
343
realm.setRoleNameCol("role_name");
344
345
// Configure credential handler
346
MessageDigestCredentialHandler credentialHandler = new MessageDigestCredentialHandler();
347
credentialHandler.setAlgorithm("SHA-256");
348
credentialHandler.setIterations(100000);
349
credentialHandler.setSaltLength(32);
350
realm.setCredentialHandler(credentialHandler);
351
352
// Attach to context
353
context.setRealm(realm);
354
```
355
356
### Authenticator Interface
357
358
Valve that performs authentication.
359
360
```java { .api }
361
public interface Authenticator {
362
boolean authenticate(Request request, HttpServletResponse response) throws IOException;
363
void login(String userName, String password, Request request) throws ServletException;
364
void logout(Request request);
365
}
366
```
367
368
### Security Constraint
369
370
Configuration for URL-based security constraints.
371
372
```java { .api }
373
public class SecurityConstraint implements Serializable {
374
// Constructor
375
public SecurityConstraint();
376
377
// Display name
378
public void setDisplayName(String displayName);
379
public String getDisplayName();
380
381
// Auth constraint
382
public void setAuthConstraint(boolean authConstraint);
383
public boolean getAuthConstraint();
384
public void addAuthRole(String authRole);
385
public boolean findAuthRole(String role);
386
public String[] findAuthRoles();
387
public void removeAuthRole(String authRole);
388
389
// User data constraint
390
public void setUserConstraint(String userConstraint);
391
public String getUserConstraint();
392
393
// Collections
394
public void addCollection(SecurityCollection collection);
395
public SecurityCollection[] findCollections();
396
public void removeCollection(SecurityCollection collection);
397
}
398
399
public class SecurityCollection implements Serializable {
400
// Constructor
401
public SecurityCollection();
402
public SecurityCollection(String name);
403
404
// Name and description
405
public void setName(String name);
406
public String getName();
407
public void setDescription(String description);
408
public String getDescription();
409
410
// URL patterns
411
public void addPattern(String pattern);
412
public boolean findPattern(String pattern);
413
public String[] findPatterns();
414
public void removePattern(String pattern);
415
416
// HTTP methods
417
public void addMethod(String method);
418
public boolean findMethod(String method);
419
public String[] findMethods();
420
public void removeMethod(String method);
421
422
// Omitted HTTP methods
423
public void addOmittedMethod(String method);
424
public boolean findOmittedMethod(String method);
425
public String[] findOmittedMethods();
426
public void removeOmittedMethod(String method);
427
}
428
429
public class LoginConfig implements Serializable {
430
// Constructor
431
public LoginConfig();
432
433
// Authentication method
434
public void setAuthMethod(String authMethod);
435
public String getAuthMethod();
436
437
// Realm name
438
public void setRealmName(String realmName);
439
public String getRealmName();
440
441
// Login and error pages (for FORM authentication)
442
public void setLoginPage(String loginPage);
443
public String getLoginPage();
444
public void setErrorPage(String errorPage);
445
public String getErrorPage();
446
}
447
```
448
449
### JASPIC Support
450
451
Jakarta Authentication (JASPIC) interfaces.
452
453
```java { .api }
454
// Server authentication module
455
public interface ServerAuthModule {
456
void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy,
457
CallbackHandler handler, Map<String,Object> options) throws AuthException;
458
AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject,
459
Subject serviceSubject) throws AuthException;
460
AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject)
461
throws AuthException;
462
void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException;
463
Class<?>[] getSupportedMessageTypes();
464
}
465
466
// Authentication status
467
public class AuthStatus {
468
public static final AuthStatus SUCCESS;
469
public static final AuthStatus FAILURE;
470
public static final AuthStatus SEND_SUCCESS;
471
public static final AuthStatus SEND_FAILURE;
472
public static final AuthStatus SEND_CONTINUE;
473
}
474
475
// Message info
476
public interface MessageInfo {
477
Object getRequestMessage();
478
Object getResponseMessage();
479
void setRequestMessage(Object request);
480
void setResponseMessage(Object response);
481
Map<String,Object> getMap();
482
}
483
```
484
485
## Usage Examples
486
487
### Basic Authentication Configuration
488
489
```java
490
import org.apache.catalina.startup.Tomcat;
491
import org.apache.catalina.Context;
492
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
493
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
494
import org.apache.tomcat.util.descriptor.web.LoginConfig;
495
496
public class BasicAuthExample {
497
public static void main(String[] args) throws Exception {
498
Tomcat tomcat = new Tomcat();
499
tomcat.setPort(8080);
500
501
Context ctx = tomcat.addWebapp("/secure", "/path/to/webapp");
502
503
// Add users
504
tomcat.addUser("admin", "admin123");
505
tomcat.addRole("admin", "manager");
506
507
// Add security constraint
508
SecurityConstraint constraint = new SecurityConstraint();
509
constraint.setAuthConstraint(true);
510
constraint.addAuthRole("manager");
511
512
SecurityCollection collection = new SecurityCollection();
513
collection.addPattern("/admin/*");
514
constraint.addCollection(collection);
515
516
ctx.addConstraint(constraint);
517
518
// Configure login
519
LoginConfig config = new LoginConfig();
520
config.setAuthMethod("BASIC");
521
config.setRealmName("Protected Area");
522
ctx.setLoginConfig(config);
523
524
tomcat.start();
525
tomcat.getServer().await();
526
}
527
}
528
```
529