or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

acl-services.mdcaching-performance.mdconfiguration.mddomain-model.mdindex.mdpermission-evaluation.mdstrategy-interfaces.md

domain-model.mddocs/

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.