Согласно Spring Security 3.1 от PacktPub :
К сожалению, фактическая реализация AclImpl
напрямую сравнивает разрешение, указанное в нашем выражении SpEL в нашей аннотации [@PostFilter
], и разрешение, сохраненное в ACE в базе данных, без использования побитовой логики . Сообщество Spring Security спорит о том, является ли это непреднамеренным или работает как задумано. , .
Пример в этой книге пытается сделать именно то, что вы описываете - он указывает пользователя с ролью 3 для чтение / запись , но пользователю отказано доступ к объекту с маской разрешения 1 для чтение .
Решение - написать собственный оценщик разрешений.
MyPermissionEvaluator.java :
public class MyPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object requiredPermissions) {
//some way to access your user's assigned permission mask
int permissionMask = MyUserDetails.getMask();
//the requiredPermissions object must be cast as a String, and then
//converted to an integer, even though it is an integer in the ACL table
int permissionsRequired = Integer.valueOf(requiredPermissions.toString());
//a simple bitwise OR will identify whether the user has the required permissions
return ((permissionMask | permissionsRequired) == permissionMask);
}
. . .
}
Чтобы использовать этот пользовательский оценщик разрешений, отредактируйте файл security.xml
:
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<bean id="espressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>
<bean id="permissionEvaluator" class="my.project.package.MyPermissionEvaluator"/>
Наконец, всякий раз, когда метод или класс требуют определенного уровня разрешения:
@PreAuthorize("hasPermission(#this, '4')")
public void mySecuredMethod() { //some secured method
}
Теперь вы можете установить маску разрешений в таблице ACL для того, что соответствует вашим организационным потребностям (побитовым), и делать то же самое любым способом, которым вы идентифицируете разрешения каждого отдельного пользователя. Например,
user site_admin_bit database_admin_bit edit_data_bit write_data_bit read_data_bit
nancy 0 1 1 0 1
Таким образом, Нэнси имеет маску разрешений 13 (из возможных 31 ), как хранится в вашей реализации пользовательских данных. Если она попытается получить доступ к объекту с требованием разрешения edit_data
, ее разрешения будут проверены по требованию маски 4 , а оценка побитового ИЛИ (permissionMask | permissionsRequired == permissionMask
) оценивается как true
.
Это, по моей оценке, самый простой способ реализовать побитовую маску разрешений для организации (с 32-битной игрой, которой, мне кажется, должно хватить). Согласно указанной книге, выражение hasPermission
SpEL, используемое в аннотациях Spring, оценивает права пользователя как единое целое; если для пользователя установлено разрешение 3 для чтения / записи, но аннотация сравнивается только с read (1 ), пользователю будет отказано в доступе.