问题
I can use Spring Security ACL with permissions on entity but I'd like to know how to test if a user has access to the "create" (bit 2) permission on a class.
Something like :
aclPermissionEvaluator.hasPermission(auth, clazz, "create")
Could someone help me?
Thanks in advance
回答1:
You can use Spring's SpEL annotations, e.g. @PreAuthorize
, and override the hasPermission
method of the PermissionEvaluator
interface. If you're using bitwise permission masks, and the user's permissions (as an int
) evaluate to '15' (1111
), and the required permissions for the object are '6' (0110
), you can do something like the following:
public boolean hasPermission(Authentication auth, Object targetObject, Object requiredPermissions) {
int permissionMask = MyUserClass.getMask();
int permissionsRequired = Integer.valueOf(requiredPermissions.toString());
return ((permissionMask | requiredPermissions) == permissionMask);
}
This will return true whenever the bits active in the object's permissions mask are active on the user's permissions. Then, you'd need to declare this custom permission evaluator in your security.xml
file:
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>
<bean id="permissionEvaluator" class="my.project.package.CustomPermissionEvaluator"/>
Now, whenever you call hasPermission()
, your custom evaluator will handle the request. Obviously, you can use whatever logic you like to evaluate permissions -- just make sure the return type is boolean
, and the parameters to be passed match what you're sending (or evaluating against; be careful of format exceptions).
Note that your custom parameter must be passed as an Object
to override hasPermission()
; you could also overload the method by changing the signature to handle whatever parameter type you prefer (e.g. String or int), and the compiler should select the most specific signature. Since you're implementing the PermissionEvaluator interface, however, you'll have to include the given signature (Authentication, Object, Object) anyway, so unless you have some specific need to write an overload method, you may as well just override.
回答2:
I have exactly the same problem, and sadly, there is no "out of the box" solutions.
One way to do it, if your domain model allow for it, is to add the create permission to the parent object you want to create
For example, imagine you want to create an user for a client. You can add the create permission to the client for the user allowed to create user for this specific client. That the path I choose.
If your domain object doesn't allow for that, the only way I found to do it is:
- to create a new table
acl_class_entry
, wich listacl_entry
equivalent but linked to anacl_class
and not to anacl_object_identity
- Then you create your own permission evaluator, surcharging the method
boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission)
to check the permission against theacl_class_entry
iftarget_id
is null. This will allow you to check permission against a class by using the SPel expressionhasPermission(nulll, 'className', 'permission')
- Of course, you will also need to create your own version of
AclService
for creating such permission.
来源:https://stackoverflow.com/questions/16188277/spring-security-acl-create-permission