CustomSecurityExpressionRoot 类必须扩展 MethodSecurityExpressionRoot!
(实现MethodSecurityExpressionOperations)是不够的。
不幸的是MethodSecurityExpressionRoot 是一个包保护类。
- 因此,您需要将
CustomSecurityExpressionRoot 放在同一个包中(org.springframework.security.access.expression.method)
- 或者您将以下类用作
CustomSecurityExpressionRoot 的超类(这就是我在项目中所做的)
ExtensibleMethodSecurityExpressionRoot:
package org.springframework.security.access.expression.method;
import org.springframework.security.core.Authentication;
/** Makes the class {@link MethodSecurityExpressionRoot} public to other packages. */
public class ExtensibleMethodSecurityExpressionRoot extends MethodSecurityExpressionRoot {
/**
* Instantiates a new extensible method security expression root.
* @param a the Authentication
*/
public ExtensibleMethodSecurityExpressionRoot(final Authentication a) {
super(a);
}
}
我的完整方法是这样的:
ExtensibleMethodSecurityExpressionHandler 更改评估根上下文:
package org.springframework.security.access.expression.method;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.DenyAllPermissionEvaluator;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.access.expression.method.defaultexpression.DefaultMethodSecuritiyExpressionRootFactory;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
/**
* This class is the same like {@link MethodSecurityExpressionHandler} but its evaluation
* root context can be exchanged.
* To use an other evaluation root context, set an other {@link #methodSecurityExpRootFactory}.
*
*/
public class ExtensibleMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
/** The parameter name discoverer. */
private ParameterNameDiscoverer parameterNameDiscoverer;
/** The permission evaluator. */
private PermissionEvaluator permissionEvaluator;
/** The trust resolver. */
private AuthenticationTrustResolver trustResolver;
/** The expression parser. */
private ExpressionParser expressionParser;
/** The method security expression root factory. */
private MethodSecurityExpressionRootFactory<?> methodSecurityExpRootFactory;
/** The role hierarchy. */
private RoleHierarchy roleHierarchy;
/**
* Instantiates a new extensible method security expression handler.
*/
public ExtensibleMethodSecurityExpressionHandler() {
this.parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
this.permissionEvaluator = new DenyAllPermissionEvaluator();
this.trustResolver = new AuthenticationTrustResolverImpl();
this.expressionParser = new SpelExpressionParser();
this.methodSecurityExpRootFactory = new DefaultMethodSecuritiyExpressionRootFactory();
}
/**
* Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
* configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object.
*
* @param auth the auth
* @param mi the mi
* @return the evaluation context
*/
@Override
public EvaluationContext createEvaluationContext(final Authentication auth, final MethodInvocation mi) {
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth,
mi,
this.parameterNameDiscoverer);
MethodSecurityExpressionRoot root = this.methodSecurityExpRootFactory.createMethodSecurityExpressionRoot(auth);
root.setTrustResolver(this.trustResolver);
root.setPermissionEvaluator(this.permissionEvaluator);
root.setRoleHierarchy(this.roleHierarchy);
ctx.setRootObject(root);
return ctx;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.security.access.expression.method.MethodSecurityExpressionHandler#filter(java.lang.Object,
* org.springframework.expression.Expression, org.springframework.expression.EvaluationContext)
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object filter(final Object filterTarget, final Expression filterExpression, final EvaluationContext ctx) {
MethodSecurityExpressionRoot rootObject = (MethodSecurityExpressionRoot) ctx.getRootObject().getValue();
List retainList;
if (filterTarget instanceof Collection) {
Collection collection = (Collection) filterTarget;
retainList = new ArrayList(collection.size());
for (Object filterObject : (Collection) filterTarget) {
rootObject.setFilterObject(filterObject);
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retainList.add(filterObject);
}
}
collection.clear();
collection.addAll(retainList);
return filterTarget;
}
if (filterTarget.getClass().isArray()) {
Object[] array = (Object[]) filterTarget;
retainList = new ArrayList(array.length);
for (Object element : array) {
rootObject.setFilterObject(element);
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retainList.add(element);
}
}
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 or array type, but was " + filterTarget);
}
/*
* (non-Javadoc)
*
* @see org.springframework.security.access.expression.method.MethodSecurityExpressionHandler#getExpressionParser()
*/
@Override
public ExpressionParser getExpressionParser() {
return this.expressionParser;
}
/**
* Sets the parameter name discoverer.
*
* @param parameterNameDiscoverer the new parameter name discoverer
*/
public void setParameterNameDiscoverer(final ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
}
/**
* Sets the permission evaluator.
*
* @param permissionEvaluator the new permission evaluator
*/
public void setPermissionEvaluator(final PermissionEvaluator permissionEvaluator) {
this.permissionEvaluator = permissionEvaluator;
}
/**
* Sets the trust resolver.
*
* @param trustResolver the new trust resolver
*/
public void setTrustResolver(final AuthenticationTrustResolver trustResolver) {
this.trustResolver = trustResolver;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.security.access.expression.method.MethodSecurityExpressionHandler#setReturnObject(java.lang
* .Object, org.springframework.expression.EvaluationContext)
*/
@Override
public void setReturnObject(final Object returnObject, final EvaluationContext ctx) {
((MethodSecurityExpressionRoot) ctx.getRootObject().getValue()).setReturnObject(returnObject);
}
/**
* Sets the role hierarchy.
*
* @param roleHierarchy the new role hierarchy
*/
public void setRoleHierarchy(final RoleHierarchy roleHierarchy) {
this.roleHierarchy = roleHierarchy;
}
/**
* Gets the method security expression root factory.
*
* @return the method security expression root factory
*/
public MethodSecurityExpressionRootFactory<?> getMethodSecurityExpressionRootFactory() {
return this.methodSecurityExpRootFactory;
}
/**
* Sets the method security expression root factory.
*
* @param methodSecurityExpressionRootFactory the new method security expression root factory
*/
public void setMethodSecurityExpressionRootFactory(
final MethodSecurityExpressionRootFactory<?> methodSecurityExpressionRootFactory) {
this.methodSecurityExpRootFactory = methodSecurityExpressionRootFactory;
}
/**
* Gets the parameter name discoverer.
*
* @return the parameter name discoverer
*/
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
}
/**
* Gets the permission evaluator.
*
* @return the permission evaluator
*/
public PermissionEvaluator getPermissionEvaluator() {
return this.permissionEvaluator;
}
/**
* Gets the trust resolver.
*
* @return the trust resolver
*/
public AuthenticationTrustResolver getTrustResolver() {
return this.trustResolver;
}
/**
* Gets the role hierarchy.
*
* @return the role hierarchy
*/
public RoleHierarchy getRoleHierarchy() {
return this.roleHierarchy;
}
/**
* Sets the expression parser.
*
* @param expressionParser the new expression parser
*/
public void setExpressionParser(final ExpressionParser expressionParser) {
this.expressionParser = expressionParser;
}
}
MethodSecurityExpressionRootFactory:
package org.springframework.security.access.expression.method;
import org.springframework.security.core.Authentication;
/**
* Factory Class/Template Class-Pattern: Template Class interface to create different expression root objects.
*
* @param <T> the {@link ExtensibleMethodSecurityExpressionRoot} created by this factory.
*/
public interface MethodSecurityExpressionRootFactory<T extends ExtensibleMethodSecurityExpressionRoot> {
/**
* Creates a new MethodSecurityExpressionRoot object.
*
* @param authentication the authentication
* @return the extensible method security expression root
*/
T createMethodSecurityExpressionRoot(final Authentication authentication);
}
DefaultMethodSecuritiyExpressionRootFactory:仅当想要使用没有自己扩展的 ExtensibleMethodSecurityExpression 处理程序时才需要
package org.springframework.security.access.expression.method.defaultexpression;
import org.springframework.security.access.expression.method.ExtensibleMethodSecurityExpressionRoot;
import org.springframework.security.access.expression.method.MethodSecurityExpressionRootFactory;
import org.springframework.security.core.Authentication;
/**
* Create the default {@link ExtensibleMethodSecurityExpressionRoot} expression root.
*/
public class DefaultMethodSecuritiyExpressionRootFactory implements
MethodSecurityExpressionRootFactory<ExtensibleMethodSecurityExpressionRoot> {
@Override
public ExtensibleMethodSecurityExpressionRoot createMethodSecurityExpressionRoot(final Authentication auth) {
return new ExtensibleMethodSecurityExpressionRoot(auth);
}
}
示例自定义方法表达式根
package com.queomedia.vwcotool.infrastructure.security.spring;
import org.springframework.security.access.expression.method.ExtensibleMethodSecurityExpressionRoot;
import org.springframework.security.core.Authentication;
public class VwCoToolMethodSecurityExpressionRoot extends ExtensibleMethodSecurityExpressionRoot {
private Authentication a;
public MyMethodSecurityExpressionRoot(final Authentication a) {
super(a);
this.a = a;
}
public isXXX(final DomainObject x){
return x.getCreator().getName().equals(a.getPrincipal());
}
}