0
# Core Domain Model
1
2
Spring Security ACL's domain model provides a clean abstraction for representing access control lists and their components. Understanding these core interfaces is essential for working with the ACL module.
3
4
## Overview
5
6
The domain model consists of seven core interfaces that work together to represent permissions:
7
8
- **`Acl`** - Contains access control entries for a domain object (read-only view)
9
- **`MutableAcl`** - Extends Acl with modification capabilities
10
- **`ObjectIdentity`** - Identifies a specific domain object instance
11
- **`Sid`** - Represents a security identity (user or role)
12
- **`Permission`** - Defines the type of access being granted
13
- **`AccessControlEntry`** - Individual permission assignment within an ACL
14
- **`AuditableAccessControlEntry`** - ACE with audit success/failure tracking
15
16
## Core Interfaces
17
18
### Acl Interface
19
20
The `Acl` interface represents an access control list for a domain object:
21
22
```java { .api }
23
package org.springframework.security.acls.model;
24
25
public interface Acl extends Serializable {
26
27
// Get all ACL entries (for administrative purposes)
28
List<AccessControlEntry> getEntries();
29
30
// Get the domain object this ACL protects
31
ObjectIdentity getObjectIdentity();
32
33
// Get the owner of this ACL
34
Sid getOwner();
35
36
// Get parent ACL for inheritance
37
Acl getParentAcl();
38
39
// Check if entries inherit from parent
40
boolean isEntriesInheriting();
41
42
// Main authorization method
43
boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
44
throws NotFoundException, UnloadedSidException;
45
46
// Check if specific SIDs are loaded
47
boolean isSidLoaded(List<Sid> sids);
48
}
49
```
50
51
**Key Points:**
52
- `isGranted()` is the primary method for authorization decisions
53
- ACLs can inherit entries from parent ACLs
54
- Not all SIDs need to be loaded for performance optimization
55
- Entries are ordered and this ordering affects permission evaluation
56
57
### MutableAcl Interface
58
59
The `MutableAcl` interface extends `Acl` to provide modification capabilities:
60
61
```java { .api }
62
package org.springframework.security.acls.model;
63
64
public interface MutableAcl extends Acl {
65
66
// Get the ACL identifier
67
Serializable getId();
68
69
// Insert new ACE at specific index
70
void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting)
71
throws NotFoundException;
72
73
// Update permission for existing ACE
74
void updateAce(int aceIndex, Permission permission) throws NotFoundException;
75
76
// Remove ACE at specific index
77
void deleteAce(int aceIndex) throws NotFoundException;
78
79
// Change ACL ownership
80
void setOwner(Sid newOwner);
81
82
// Set parent ACL for inheritance
83
void setParent(Acl newParent);
84
85
// Control inheritance behavior
86
void setEntriesInheriting(boolean entriesInheriting);
87
}
88
```
89
90
**Key Points:**
91
- All modification operations require appropriate security authorization
92
- ACE ordering is significant - earlier entries take precedence
93
- Index-based operations for precise control over ACE placement
94
- Provides full lifecycle management for ACL entries
95
96
### ObjectIdentity Interface
97
98
Represents the identity of a domain object instance:
99
100
```java { .api }
101
package org.springframework.security.acls.model;
102
103
public interface ObjectIdentity extends Serializable {
104
105
// Get the object's unique identifier
106
Serializable getIdentifier();
107
108
// Get the object's type/class name
109
String getType();
110
111
// Standard equality methods
112
boolean equals(Object obj);
113
int hashCode();
114
}
115
```
116
117
**Implementation Example:**
118
```java { .api }
119
// Using ObjectIdentityImpl for different scenarios
120
ObjectIdentity docId = new ObjectIdentityImpl(Document.class, 123L);
121
ObjectIdentity customId = new ObjectIdentityImpl("com.example.Document", "DOC-456");
122
ObjectIdentity fromObject = new ObjectIdentityImpl(documentInstance);
123
```
124
125
### Sid Interface
126
127
Represents a security identity - either a principal (user) or granted authority (role):
128
129
```java { .api }
130
package org.springframework.security.acls.model;
131
132
public interface Sid extends Serializable {
133
boolean equals(Object obj);
134
int hashCode();
135
}
136
```
137
138
**Built-in Implementations:**
139
140
```java { .api }
141
// Principal-based SID (represents a user)
142
public class PrincipalSid implements Sid {
143
public PrincipalSid(String principal);
144
public PrincipalSid(Authentication authentication);
145
public String getPrincipal();
146
}
147
148
// Authority-based SID (represents a role/group)
149
public class GrantedAuthoritySid implements Sid {
150
public GrantedAuthoritySid(String grantedAuthority);
151
public GrantedAuthoritySid(GrantedAuthority grantedAuthority);
152
public String getGrantedAuthority();
153
}
154
```
155
156
**Usage Examples:**
157
```java { .api }
158
// Create SIDs for different scenarios
159
Sid userSid = new PrincipalSid("john.doe");
160
Sid adminSid = new GrantedAuthoritySid("ROLE_ADMIN");
161
Sid managerSid = new GrantedAuthoritySid("ROLE_DOCUMENT_MANAGER");
162
163
// From Spring Security Authentication
164
Sid currentUser = new PrincipalSid(authentication);
165
List<Sid> userAuthorities = authentication.getAuthorities()
166
.stream()
167
.map(GrantedAuthoritySid::new)
168
.collect(Collectors.toList());
169
```
170
171
### Permission Interface
172
173
Represents a permission that can be granted or denied:
174
175
```java { .api }
176
package org.springframework.security.acls.model;
177
178
public interface Permission extends Serializable {
179
180
// Get the permission bitmask
181
int getMask();
182
183
// Get human-readable pattern representation
184
String getPattern();
185
186
// Constants for pattern display
187
char RESERVED_ON = '~';
188
char RESERVED_OFF = '.';
189
String THIRTY_TWO_RESERVED_OFF = "................................";
190
}
191
```
192
193
**Built-in Permissions:**
194
```java { .api }
195
public class BasePermission extends AbstractPermission {
196
197
public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
198
public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
199
public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
200
public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
201
public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
202
203
protected BasePermission(int mask);
204
protected BasePermission(int mask, char code);
205
}
206
```
207
208
**Custom Permissions:**
209
```java { .api }
210
public class CustomPermission extends AbstractPermission {
211
public static final Permission APPROVE = new CustomPermission(1 << 5, 'P');
212
public static final Permission PUBLISH = new CustomPermission(1 << 6, 'U');
213
214
public CustomPermission(int mask, char code) {
215
super(mask, code);
216
}
217
}
218
```
219
220
### AccessControlEntry Interface
221
222
Represents an individual permission assignment within an ACL:
223
224
```java { .api }
225
package org.springframework.security.acls.model;
226
227
public interface AccessControlEntry extends Serializable {
228
229
// Get the ACL this entry belongs to
230
Acl getAcl();
231
232
// Get unique identifier for this entry
233
Serializable getId();
234
235
// Get the permission being granted/denied
236
Permission getPermission();
237
238
// Get the security identity
239
Sid getSid();
240
241
// Check if this is a grant (true) or deny (false)
242
boolean isGranting();
243
}
244
```
245
246
**Extended Interface for Auditing:**
247
```java { .api }
248
public interface AuditableAccessControlEntry extends AccessControlEntry {
249
boolean isAuditFailure();
250
boolean isAuditSuccess();
251
}
252
```
253
254
## Extended Interfaces
255
256
The ACL module provides additional specialized interfaces:
257
258
### Extended Mutable Interfaces
259
260
```java { .api }
261
// For ownership operations
262
public interface OwnershipAcl extends MutableAcl {
263
void setOwner(Sid newOwner);
264
}
265
266
// For audit configuration
267
public interface AuditableAcl extends MutableAcl {
268
void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure);
269
}
270
```
271
272
## Relationships and Interactions
273
274
### ACL Structure
275
276
```java { .api }
277
// An ACL contains multiple ACEs
278
Acl documentAcl = aclService.readAclById(objectIdentity);
279
List<AccessControlEntry> entries = documentAcl.getEntries();
280
281
for (AccessControlEntry ace : entries) {
282
Sid sid = ace.getSid();
283
Permission permission = ace.getPermission();
284
boolean isGrant = ace.isGranting();
285
286
System.out.printf("SID: %s, Permission: %s, Grant: %s%n",
287
sid, permission.getPattern(), isGrant);
288
}
289
```
290
291
### Permission Checking Flow
292
293
```java { .api }
294
// 1. Get object identity
295
ObjectIdentity identity = new ObjectIdentityImpl(Document.class, documentId);
296
297
// 2. Get current user's SIDs
298
List<Sid> sids = Arrays.asList(
299
new PrincipalSid(authentication.getName()),
300
new GrantedAuthoritySid("ROLE_USER")
301
);
302
303
// 3. Define required permissions
304
List<Permission> permissions = Arrays.asList(BasePermission.READ);
305
306
// 4. Load ACL and check permissions
307
Acl acl = aclService.readAclById(identity, sids);
308
boolean granted = acl.isGranted(permissions, sids, false);
309
```
310
311
### ACL Inheritance
312
313
```java { .api }
314
// Parent-child relationship example
315
ObjectIdentity parentFolder = new ObjectIdentityImpl(Folder.class, parentId);
316
ObjectIdentity childDocument = new ObjectIdentityImpl(Document.class, documentId);
317
318
// Child ACL can inherit from parent
319
MutableAcl childAcl = aclService.createAcl(childDocument);
320
Acl parentAcl = aclService.readAclById(parentFolder);
321
322
childAcl.setParent(parentAcl);
323
childAcl.setEntriesInheriting(true); // Enable inheritance
324
aclService.updateAcl(childAcl);
325
326
// Permission check will consider both child and parent entries
327
boolean hasAccess = childAcl.isGranted(Arrays.asList(BasePermission.READ), sids, false);
328
```
329
330
## Strategy Interfaces
331
332
The ACL module provides several strategy interfaces for customization:
333
334
### ObjectIdentityRetrievalStrategy
335
336
```java { .api }
337
public interface ObjectIdentityRetrievalStrategy {
338
ObjectIdentity getObjectIdentity(Object domainObject);
339
}
340
341
// Default implementation
342
public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy {
343
public ObjectIdentity getObjectIdentity(Object domainObject) {
344
return new ObjectIdentityImpl(domainObject);
345
}
346
}
347
```
348
349
### SidRetrievalStrategy
350
351
```java { .api }
352
public interface SidRetrievalStrategy {
353
List<Sid> getSids(Authentication authentication);
354
}
355
356
// Default implementation
357
public class SidRetrievalStrategyImpl implements SidRetrievalStrategy {
358
public List<Sid> getSids(Authentication authentication) {
359
List<Sid> sids = new ArrayList<>();
360
sids.add(new PrincipalSid(authentication));
361
362
for (GrantedAuthority authority : authentication.getAuthorities()) {
363
sids.add(new GrantedAuthoritySid(authority));
364
}
365
return sids;
366
}
367
}
368
```
369
370
### PermissionFactory
371
372
```java { .api }
373
public interface PermissionFactory {
374
Permission buildFromMask(int mask);
375
Permission buildFromName(String name);
376
List<Permission> buildFromNames(List<String> names);
377
}
378
379
// Usage example
380
@Bean
381
public PermissionFactory permissionFactory() {
382
DefaultPermissionFactory factory = new DefaultPermissionFactory();
383
384
// Register custom permissions
385
Map<String, Permission> customPermissions = new HashMap<>();
386
customPermissions.put("APPROVE", CustomPermission.APPROVE);
387
customPermissions.put("PUBLISH", CustomPermission.PUBLISH);
388
389
factory.registerPublicPermissions(CustomPermission.class);
390
return factory;
391
}
392
```
393
394
## Exception Handling
395
396
The ACL module defines several specific exceptions:
397
398
```java { .api }
399
// Base exception for ACL operations
400
public abstract class AclDataAccessException extends DataAccessException {
401
protected AclDataAccessException(String msg);
402
protected AclDataAccessException(String msg, Throwable cause);
403
}
404
405
// Specific exceptions
406
public class NotFoundException extends AclDataAccessException;
407
public class AlreadyExistsException extends AclDataAccessException;
408
public class ChildrenExistException extends AclDataAccessException;
409
public class UnloadedSidException extends AclDataAccessException;
410
```
411
412
**Exception Handling Example:**
413
```java { .api }
414
try {
415
Acl acl = aclService.readAclById(objectIdentity);
416
return acl.isGranted(permissions, sids, false);
417
} catch (NotFoundException e) {
418
// No ACL exists - apply default policy
419
return false;
420
} catch (UnloadedSidException e) {
421
// Requested SID not loaded - reload with all SIDs
422
Acl fullAcl = aclService.readAclById(objectIdentity);
423
return fullAcl.isGranted(permissions, sids, false);
424
}
425
```
426
427
## Best Practices
428
429
### 1. Use Appropriate SID Types
430
```java { .api }
431
// Use PrincipalSid for user-specific permissions
432
Sid userSid = new PrincipalSid("john.doe");
433
434
// Use GrantedAuthoritySid for role-based permissions
435
Sid roleSid = new GrantedAuthoritySid("ROLE_DOCUMENT_ADMIN");
436
```
437
438
### 2. Leverage ACL Inheritance
439
```java { .api }
440
// Set up hierarchical permissions
441
MutableAcl folderAcl = aclService.createAcl(folderIdentity);
442
folderAcl.insertAce(0, BasePermission.READ, managerSid, true);
443
444
MutableAcl documentAcl = aclService.createAcl(documentIdentity);
445
documentAcl.setParent(folderAcl);
446
documentAcl.setEntriesInheriting(true);
447
// Documents inherit folder permissions automatically
448
```
449
450
### 3. Optimize for Performance
451
```java { .api }
452
// Load ACLs with specific SIDs for better performance
453
List<Sid> relevantSids = sidRetrievalStrategy.getSids(authentication);
454
Acl acl = aclService.readAclById(objectIdentity, relevantSids);
455
```
456
457
### 4. Use Custom Permissions Appropriately
458
```java { .api }
459
// Define business-specific permissions
460
public class DocumentPermission extends AbstractPermission {
461
public static final Permission APPROVE = new DocumentPermission(1 << 5, 'P');
462
public static final Permission PUBLISH = new DocumentPermission(1 << 6, 'U');
463
public static final Permission ARCHIVE = new DocumentPermission(1 << 7, 'H');
464
}
465
```
466
467
The domain model provides a flexible foundation for implementing fine-grained access control. The next step is understanding how to [configure and use ACL services](acl-services.md) to work with this domain model.