Skip to content

Commit 3aec6c2

Browse files
committed
Deprecate Access API in ACL
Issue gh-11302
1 parent 05fdcd6 commit 3aec6c2

File tree

8 files changed

+155
-6
lines changed

8 files changed

+155
-6
lines changed

acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@
9696
* All comparisons and prefixes are case sensitive.
9797
*
9898
* @author Ben Alex
99+
* @deprecated please use {@link AclPermissionEvaluator} instead. Spring Method Security annotations
100+
* may also prove useful, for example {@code @PreAuthorize("hasPermission(#id, ObjectsReturnType.class, read)")}
99101
*/
102+
@Deprecated
100103
public class AclEntryVoter extends AbstractAclVoter {
101104

102105
private static final Log logger = LogFactory.getLog(AclEntryVoter.class);

acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.springframework.security.access.AfterInvocationProvider;
2222
import org.springframework.security.access.ConfigAttribute;
23+
import org.springframework.security.acls.AclPermissionEvaluator;
2324
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
2425
import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
2526
import org.springframework.security.acls.model.Acl;
@@ -39,7 +40,10 @@
3940
* services.
4041
*
4142
* @author Ben Alex
43+
* @deprecated please use {@link AclPermissionEvaluator} instead. Spring Method Security annotations
44+
* may also prove useful, for example {@code @PostAuthorize("hasPermission(filterObject, read)")}
4245
*/
46+
@Deprecated
4347
public abstract class AbstractAclProvider implements AfterInvocationProvider {
4448

4549
protected final AclService aclService;

acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.security.access.AccessDeniedException;
2727
import org.springframework.security.access.AuthorizationServiceException;
2828
import org.springframework.security.access.ConfigAttribute;
29+
import org.springframework.security.acls.AclPermissionEvaluator;
2930
import org.springframework.security.acls.model.AclService;
3031
import org.springframework.security.acls.model.Permission;
3132
import org.springframework.security.core.Authentication;
@@ -62,7 +63,10 @@
6263
*
6364
* @author Ben Alex
6465
* @author Paulo Neves
66+
* @deprecated please use {@link AclPermissionEvaluator} instead. Spring Method Security annotations
67+
* may also prove useful, for example {@code @PostFilter("hasPermission(filterObject, read)")}
6568
*/
69+
@Deprecated
6670
public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider {
6771

6872
protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class);

acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.context.support.MessageSourceAccessor;
2828
import org.springframework.security.access.AccessDeniedException;
2929
import org.springframework.security.access.ConfigAttribute;
30+
import org.springframework.security.acls.AclPermissionEvaluator;
3031
import org.springframework.security.acls.model.AclService;
3132
import org.springframework.security.acls.model.Permission;
3233
import org.springframework.security.core.Authentication;
@@ -59,7 +60,10 @@
5960
* granted and <code>null</code> will be returned.
6061
* <p>
6162
* All comparisons and prefixes are case sensitive.
63+
* @deprecated please use {@link AclPermissionEvaluator} instead. Spring Method Security annotations
64+
* may also prove useful, for example {@code @PostAuthorize("hasPermission(filterObject, read)")}
6265
*/
66+
@Deprecated
6367
public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware {
6468

6569
protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class);

acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
*
3333
* @author Ben Alex
3434
* @author Paulo Neves
35+
* @deprecated please see {@code PostFilter}
3536
*/
37+
@Deprecated
3638
class ArrayFilterer<T> implements Filterer<T> {
3739

3840
protected static final Log logger = LogFactory.getLog(ArrayFilterer.class);

acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
*
3232
* @author Ben Alex
3333
* @author Paulo Neves
34+
* @deprecated please see {@code PostFilter}
3435
*/
36+
@Deprecated
3537
class CollectionFilterer<T> implements Filterer<T> {
3638

3739
protected static final Log logger = LogFactory.getLog(CollectionFilterer.class);

acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
*
2424
* @author Ben Alex
2525
* @author Paulo Neves
26+
* @deprecated please use {@code PreFilter} and {@code @PostFilter} instead
2627
*/
28+
@Deprecated
2729
interface Filterer<T> extends Iterable<T> {
2830

2931
/**

docs/modules/ROOT/pages/servlet/authorization/acls.adoc

Lines changed: 134 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,139 @@ Instead, you need to write code similar to that shown in the preceding example f
202202
You should consider using AOP on your services layer to automatically integrate the ACL information with your services layer operations.
203203
We have found this approach to be effective.
204204

205+
== Using the PermissionEvaluator
206+
205207
Once you have used the techniques described here to store some ACL information in the database, the next step is to actually use the ACL information as part of authorization decision logic.
206-
You have a number of choices here.
207-
You could write your own `AccessDecisionVoter` or `AfterInvocationProvider` that (respectively) fires before or after a method invocation.
208-
Such classes would use `AclService` to retrieve the relevant ACL and then call `Acl.isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode)` to decide whether permission is granted or denied.
209-
Alternately, you could use our `AclEntryVoter`, `AclEntryAfterInvocationProvider` or `AclEntryAfterInvocationCollectionFilteringProvider` classes.
210-
All of these classes provide a declarative-based approach to evaluating ACL information at runtime, freeing you from needing to write any code.
211208

212-
See the https://github.com/spring-projects/spring-security-samples[sample applications] to learn how to use these classes.
209+
You have a number of choices here with the primary one being using `AclPermissionEvaluator` in your `@PreAuthorize`, `@PostAuthorize`, `@PreFilter`, and `@PostFilter` annotation expressions.
210+
211+
This is a sample listing of the components needed to wire an `AclPersmissionEvaluator` into your authorization logic:
212+
213+
[tabs]
214+
======
215+
Java::
216+
+
217+
[source,java,role="primary"]
218+
----
219+
@EnableMethodSecurity
220+
@Configuration
221+
class SecurityConfig {
222+
@Bean
223+
static MethodSecurityExpressionHandler expressionHandler(AclPermissionEvaluator aclPermissionEvaluator) {
224+
final DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
225+
expressionHandler.setPermissionEvaluator(aclPermissionEvaluator);
226+
return expressionHandler;
227+
}
228+
229+
@Bean
230+
static AclPermissionEvaluator aclPermissionEvaluator(AclService aclService) {
231+
return new AclPermissionEvaluator(aclService);
232+
}
233+
234+
@Bean
235+
static JdbcMutableAclService aclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
236+
return new JdbcMutableAclService(dataSource, lookupStrategy, aclCache);
237+
}
238+
239+
@Bean
240+
static LookupStrategy lookupStrategy(DataSource dataSource, AclCache cache,
241+
AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy permissionGrantingStrategy) {
242+
return new BasicLookupStrategy(dataSource, cache, aclAuthorizationStrategy, permissionGrantingStrategy);
243+
}
244+
245+
@Bean
246+
static AclCache aclCache(PermissionGrantingStrategy permissionGrantingStrategy,
247+
AclAuthorizationStrategy aclAuthorizationStrategy) {
248+
Cache cache = new ConcurrentMapCache("aclCache");
249+
return new SpringCacheBasedAclCache(cache, permissionGrantingStrategy, aclAuthorizationStrategy);
250+
}
251+
252+
@Bean
253+
static AclAuthorizationStrategy aclAuthorizationStrategy() {
254+
return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ADMIN"));
255+
}
256+
257+
@Bean
258+
static PermissionGrantingStrategy permissionGrantingStrategy() {
259+
return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
260+
}
261+
}
262+
----
263+
264+
Kotlin::
265+
+
266+
[source,kotlin,role="secondary"]
267+
----
268+
@EnableMethodSecurity
269+
@Configuration
270+
internal object SecurityConfig {
271+
@Bean
272+
fun expressionHandler(aclPermissionEvaluator: AclPermissionEvaluator?): MethodSecurityExpressionHandler {
273+
val expressionHandler = DefaultMethodSecurityExpressionHandler()
274+
expressionHandler.setPermissionEvaluator(aclPermissionEvaluator)
275+
return expressionHandler
276+
}
277+
278+
@Bean
279+
fun aclPermissionEvaluator(aclService: AclService?): AclPermissionEvaluator {
280+
return AclPermissionEvaluator(aclService)
281+
}
282+
283+
@Bean
284+
fun aclService(dataSource: DataSource?, lookupStrategy: LookupStrategy?, aclCache: AclCache?): JdbcMutableAclService {
285+
return JdbcMutableAclService(dataSource, lookupStrategy, aclCache)
286+
}
287+
288+
@Bean
289+
fun lookupStrategy(dataSource: DataSource?, cache: AclCache?,
290+
aclAuthorizationStrategy: AclAuthorizationStrategy?, permissionGrantingStrategy: PermissionGrantingStrategy?): LookupStrategy {
291+
return BasicLookupStrategy(dataSource, cache, aclAuthorizationStrategy, permissionGrantingStrategy)
292+
}
293+
294+
@Bean
295+
fun aclCache(permissionGrantingStrategy: PermissionGrantingStrategy?,
296+
aclAuthorizationStrategy: AclAuthorizationStrategy?): AclCache {
297+
val cache: Cache = ConcurrentMapCache("aclCache")
298+
return SpringCacheBasedAclCache(cache, permissionGrantingStrategy, aclAuthorizationStrategy)
299+
}
300+
301+
@Bean
302+
fun aclAuthorizationStrategy(): AclAuthorizationStrategy {
303+
return AclAuthorizationStrategyImpl(SimpleGrantedAuthority("ADMIN"))
304+
}
305+
306+
@Bean
307+
fun permissionGrantingStrategy(): PermissionGrantingStrategy {
308+
return DefaultPermissionGrantingStrategy(ConsoleAuditLogger())
309+
}
310+
}
311+
----
312+
======
313+
314+
315+
Then using xref:servlet/authorization/method-security.adoc#authorizing-with-annotations[method-based security] you can use `hasPermission` in your annotation expressions like so:
316+
317+
[tabs]
318+
======
319+
Java::
320+
+
321+
[source,java,role="primary"]
322+
----
323+
@GetMapping
324+
@PostFilter("hasPermission(filterObject, read)")
325+
Iterable<Message> getAll() {
326+
return this.messagesRepository.findAll();
327+
}
328+
----
329+
330+
Kotlin::
331+
+
332+
[source,kotlin,role="secondary"]
333+
----
334+
@GetMapping
335+
@PostFilter("hasPermission(filterObject, read)")
336+
fun getAll(): Iterable<Message> {
337+
return this.messagesRepository.findAll()
338+
}
339+
----
340+
======

0 commit comments

Comments
 (0)