Как использовать поле маски в таблице acl_entry в Spring Security 3.1? - PullRequest
5 голосов
/ 26 января 2012

Я использую реализацию ACL Spring Security 3.1.Итак, на основе учебника я создал базу данных acl со следующими таблицами:

CREATE TABLE IF NOT EXISTS `acl_class` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `class` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_2` (`class`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_entry` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `acl_object_identity` bigint(20) NOT NULL,
  `ace_order` int(11) NOT NULL,
  `sid` bigint(20) NOT NULL,
  `mask` int(11) NOT NULL,
  `granting` tinyint(1) NOT NULL,
  `audit_success` tinyint(1) NOT NULL,
  `audit_failure` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_4` (`acl_object_identity`,`ace_order`),
  KEY `foreign_fk_5` (`sid`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_object_identity` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `object_id_class` bigint(20) NOT NULL,
  `object_id_identity` bigint(20) NOT NULL,
  `parent_object` bigint(20) DEFAULT NULL,
  `owner_sid` bigint(20) DEFAULT NULL,
  `entries_inheriting` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_3` (`object_id_class`,`object_id_identity`),
  KEY `foreign_fk_1` (`parent_object`),
  KEY `foreign_fk_3` (`owner_sid`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_sid` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `principal` tinyint(1) NOT NULL,
  `sid` varchar(100) NOT NULL,
  `password` varchar(255) NOT NULL,
  `salt` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

Это прекрасно работает с аннотациями, такими как:

@PreAuthorize("hasPermission(#element, 'WRITE')")
@PostAuthorize("hasPermission(returnObject, 'READ')")

Права «Чтение» и «Запись»установлены в таблице acl_entry для маски поля.Как я понял, 1 означает «ЧИТАТЬ», 2 означает «Запись», 4 означает «Создать», 8 означает «Удалить» и 16 означает «Администрирование», потому что это кажется побитовым методом аутентификации.

  1. Вопрос: правильно ли я понял предоставление прав?
  2. Вопрос: Как указать комбинированные права, такие как «Чтение / Запись»?Могу ли я «установить» бит 0 (который является int 1) и 1 (который является int 2), чтобы я получил значение маски 1 + 2 = 3?

Теперь мне нужно создать отдельные записидля разрешения «ЧИТАТЬ» и «Запись» это не очень удобно.

Ответы [ 3 ]

5 голосов
/ 23 апреля 2013

Согласно 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 ), пользователю будет отказано в доступе.

1 голос
/ 26 января 2012

С SpringSecurity

Как упоминалось в последнем параграфе, система ACL использует целочисленную битовую маскировку.Не волнуйтесь, вам не нужно знать о точных точках сдвига битов, чтобы использовать систему ACL, но достаточно сказать, что у нас есть 32 бита, которые мы можем включить или выключить.Каждый из этих битов представляет собой разрешение, и по умолчанию разрешениями являются чтение (бит 0), запись (бит 1), создание (бит 2), удаление (бит 3) и администрирование (бит 4).Легко реализовать свой собственный экземпляр Permission, если вы хотите использовать другие разрешения, а остальная часть инфраструктуры ACL будет работать без знания ваших расширений.

@ question # 1: да, это верно.

@ вопрос № 2: вы можете использовать что-то вроде: new BasePermission(BasePermission.WRITE.getMask() | BasePermission.READ.getMask()), чтобы получить разрешение READ и WRITE.

Из документов источника:

// Prepare the information we'd like in our access control entry (ACE)
ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44));
Sid sid = new PrincipalSid("Samantha");
//Permission p = BasePermission.ADMINISTRATION;
Permission p = new BasePermission(BasePermission.WRITE.getMask() | BasePermission.READ.getMask());    

// Create or update the relevant ACL
MutableAcl acl = null;
try {
  acl = (MutableAcl) aclService.readAclById(oi);
} catch (NotFoundException nfe) {
  acl = aclService.createAcl(oi);
}

// Now grant some permissions via an access control entry (ACE)
acl.insertAce(acl.getEntries().length, p, sid, true);
aclService.updateAcl(acl);
0 голосов
/ 06 ноября 2014

Чтобы реализовать побитовую оценку разрешений, вместо реализации PermissionEvaluator, что может быть довольно сложно, вы можете переопределить DefaultPermissionGrantingStrategy своим собственным.

Это может быть ваша конфигурация Spring ACL

1) Ваша служба ACL

<bean class="org.springframework.security.acls.jdbc.JdbcMutableAclService" id="aclService">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="lookupStrategy"/>
<constructor-arg ref="aclCache"/>
</bean>

2) Ваша стратегия поиска (dataSource, aclCache и aclAuthorizationStrategy являются стратегиями по умолчанию) *

<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="aclCache"/>
<constructor-arg ref="aclAuthorizationStrategy"/>
<constructor-arg ref="permissionGrantingStrategy"/>
</bean>

3) Вот интересныйчасть, PermissionGrantingStrategy (http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/acls/model/PermissionGrantingStrategy.html)

<bean id="permissionGrantingStrategy" class="com.example.MyPermissionGrantingStrategy"/>

Здесь вы должны реализовать побитовую логику разрешений, а затем переопределить стандартную Spring по умолчанию.

Надеюсь, это может помочь

...