public
Created

DefaultMethodSecurityExpressionHandler with support for java.lang.Iterable

  • Download Gist
gistfile1.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
package org.example.security;
 
import java.lang.reflect.Array;
import java.util.*;
 
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.security.access.PermissionCacheOptimizer;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
 
/**
* Extension of {@link DefaultMethodSecurityExpressionHandler} to support {@link Iterable}
*
*/
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
 
private PermissionCacheOptimizer permissionCacheOptimizer;
 
/**
* Filters the {@code filterTarget} object (which must be either a collection or an array), by evaluating the
* supplied expression.
* <p/>
* If a {@code Collection} is used, the original instance will be modified to contain the elements for which
* the permission expression evaluates to {@code true}. For an array, a new array instance will be returned. And for Iterable same object
* will be modified.
*/
@SuppressWarnings("unchecked")
@Override
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx.getRootObject().getValue();
final boolean debug = logger.isDebugEnabled();
List retainList;
 
if (debug) {
logger.debug("Filtering with expression: " + filterExpression.getExpressionString());
}
 
if (filterTarget instanceof Iterable) {
Iterable iterable = (Iterable) filterTarget;
if (debug) {
logger.debug("Filtering iterable " + iterable);
}
 
// Not quite sure how to handle this? First create collection from iterable?
// if (permissionCacheOptimizer != null) {
// permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), iterable);
// }
Iterator iterator = iterable.iterator();
while (iterator.hasNext()) {
Object filterObject = iterator.next();
rootObject.setFilterObject(filterObject);
if (!ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
iterator.remove();
}
}
if (debug) {
logger.debug("Retaining elements: " + iterator);
}
 
return filterTarget;
}
 
if (filterTarget instanceof Collection) {
Collection collection = (Collection) filterTarget;
retainList = new ArrayList(collection.size());
 
if (debug) {
logger.debug("Filtering collection with " + collection.size() + " elements");
}
 
if (permissionCacheOptimizer != null) {
permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), collection);
}
 
for (Object filterObject : (Collection) filterTarget) {
rootObject.setFilterObject(filterObject);
 
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retainList.add(filterObject);
}
}
 
if (debug) {
logger.debug("Retaining elements: " + retainList);
}
 
collection.clear();
collection.addAll(retainList);
 
return filterTarget;
}
 
if (filterTarget.getClass().isArray()) {
Object[] array = (Object[]) filterTarget;
retainList = new ArrayList(array.length);
 
if (debug) {
logger.debug("Filtering array with " + array.length + " elements");
}
 
if (permissionCacheOptimizer != null) {
permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), Arrays.asList(array));
}
 
for (Object o : array) {
rootObject.setFilterObject(o);
 
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retainList.add(o);
}
}
 
if (debug) {
logger.debug("Retaining elements: " + retainList);
}
 
Object[] filtered = (Object[]) Array.newInstance(filterTarget.getClass().getComponentType(),
retainList.size());
for (int i = 0; i < retainList.size(); i++) {
filtered[i] = retainList.get(i);
}
 
return filtered;
}
 
throw new IllegalArgumentException("Filter target must be a collection, iterable or array type, but was " + filterTarget);
}
 
public void setPermissionCacheOptimizer(PermissionCacheOptimizer permissionCacheOptimizer) {
this.permissionCacheOptimizer = permissionCacheOptimizer;
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.