我正在为Spring安全编写自己的PermissionEvaluator,而我要做的其中一件事就是弄清楚它正在保护的方法的名称。
例如,如果没有图片中的方法名称,我会有:
postAuthorize("hasPermission(returnObject,'read')")
Event getEvent(int evendId) {
...
}
和
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
if(targetDomainObject instanceof Event) {
return hasPermission(authentication, targetDomainObject, permission);
}
return targetDomainObject == null;
}
但我还需要方法名称" getEvent"可以使用hasPermission。我可以通过在hasPermission调用中手动传入它来完成此操作,如下所示:
@PostAuthorize("hasPermission(new com.example.AuthZObject(returnObject,'getEvent'),'read')")
Event getEvent(int eventId);
但是有更多自动化的方法吗?
答案 0 :(得分:2)
@Ralph在这里非常有正确的想法。第一步是创建MethodSecurityExpressionOperations的自定义实现,该实现可以将Method存储在其上并使用它来计算表达式。例如:
public class MyMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
private Object filterObject;
private Object returnObject;
private Object target;
private Method method;
public MyMethodSecurityExpressionRoot(Authentication a) {
super(a);
}
// allow the method to be set
public void setMethod(Method m) {
this.method = m;
}
// optionally expose the method to be accessed in expressions
public Method getMethod() {
return method;
}
// create a method that will perform the check with
// the method name transparently for you
public boolean hasMethodPermission(Object target, Object permission) {
boolean result = false;
// do your calculations using the method member variable
// i.e. method.getName() and the arguments passed in
// of course you could delegate to another object if you want
// i.e.
// return hasPermission(new com.example.AuthZObject(target,method.getName()),permission));
// or you could do the logic right here
return result;
}
// implement the interface and provide setters
public void setFilterObject(Object filterObject) {
this.filterObject = filterObject;
}
public Object getFilterObject() {
return filterObject;
}
public void setReturnObject(Object returnObject) {
this.returnObject = returnObject;
}
public Object getReturnObject() {
return returnObject;
}
public void setThis(Object target) {
this.target = target;
}
public Object getThis() {
return target;
}
}
接下来扩展DefaultMethodSecurityExpressionHandler并使用自定义表达式root。
public class MySecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler{
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation){
MyMethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(authentication);
root.setThis(invocation.getThis());
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(new AuthenticationTrustResolverImpl());
root.setRoleHierarchy(getRoleHierarchy());
root.setMethod(invocation.getMethod());
return root;
}
}
配置MySecurityExpressionHandler后,您应该能够使用以下内容:
@PostAuthorize("hasMethodPermission(returnObject,'read')")
Event getEvent(int eventId);
答案 1 :(得分:1)
我不知道这是否可行,但你应该看一下DefaultMethodSecurityExpressionHandler
。这个类有两种方法:
public final EvaluationContext createEvaluationContext(Authentication authentication, T invocation) {
SecurityExpressionOperations root = createSecurityExpressionRoot(authentication, invocation);
StandardEvaluationContext ctx = createEvaluationContextInternal(authentication, invocation);
ctx.setBeanResolver(br);
ctx.setRootObject(root);
return ctx;
}
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
root.setThis(invocation.getThis());
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
return root;
}
我觉得您需要使用所需的其他字段扩展类MethodSecurityExpressionOperations
,然后您需要继承DefaultMethodSecurityExpressionHandler
并替换createSecurityExpressionRoot
方法以便它返回您的扩展MethodSecurityExpressionOperations
填充了字段。
然后,您可以向扩展的MethodSecurityExpressionOperations
添加能够访问此附加字段的新方法。