Разница между ролью и полномочиями в Spring безопасности

Существуют концепции и реализации в Spring безопасности, такие как интерфейс GrantedAuthority, чтобы получить полномочия на авторизацию/управление доступом.

Я хотел бы, чтобы это допустимые операции, такие как createSubUsers или deleteAccounts, которые я бы разрешил администратору (с ролью ROLE_ADMIN).

Я запутался как учебники/демо, которые я вижу в Интернете. Я пытаюсь подключить то, что я читаю, но я думаю, что мы рассматриваем два взаимозаменяемых.

Я вижу hasRole, потребляющую строку GrantedAuthority? Я определенно делаю это неправильно в понимании. Что это концептуально в Spring безопасности?

Как сохранить роль пользователя, отдельно от полномочий для этой роли?

Я также смотрю интерфейс org.springframework.security.core.userdetails.UserDetails, который используется в DAO, использующем аутентификацию поставщика, который потребляет User (обратите внимание на последний GrantedAuthority):

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)

Или есть ли другой способ отличить два других? Или это не поддерживается, и мы должны сделать свой собственный?

Ответ 1

Подумайте о разрешенной доверенности как о "разрешении" или "праве". Эти "разрешения" (обычно) выражаются как строки (с помощью метода getAuthority()). Эти строки позволяют вам идентифицировать разрешения и позволять вашим избирателям решать, предоставляют ли они что-либо.

Вы можете предоставить пользователям GrenderAuthority (разрешения) разные пользователи, помещая их в контекст безопасности. Вы обычно это делаете, реализуя свой собственный UserDetailsService, который возвращает реализацию UserDetails, которая возвращает необходимые GrantedAuthorities.

Роли (как они используются во многих примерах) - это просто "разрешения" с соглашением об именах, в котором говорится, что роль - это GrantedAuthority, которая начинается с префикса ROLE_. Больше ничего. Роль - это просто "Разрешенная поддержка" - "разрешение" - "право". Вы видите множество мест в spring безопасности, где роль с префиксом ROLE_ обрабатывается специально, например. в RoleVoter, где префикс ROLE_ используется по умолчанию. Это позволяет вам указывать имена ролей с префиксом ROLE_. До spring безопасности 4 эта специальная обработка "ролей" не выполнялась очень последовательно, а полномочия и роли часто обрабатывались одинаково (как вы, например, можете видеть в реализации метода hasAuthority() в SecurityExpressionRoot - который просто вызывает hasRole()). С spring Security 4 обработка ролей более согласована, а код, который имеет дело с "ролями" (например, выражение RoleVoter, hasRole и т.д.), Всегда добавляет префикс ROLE_ для вас. Таким образом, hasAuthority('ROLE_ADMIN') означает то же, что и hasRole('ADMIN'), потому что префикс ROLE_ добавляется автоматически. Подробнее см. В руководстве по безопасности spring от 3 до 4 .

Но все же: роль - это просто авторитет со специальным префиксом ROLE_. Таким образом, в spring безопасность 3 @PreAuthorize("hasRole('ROLE_XYZ')") совпадает с @PreAuthorize("hasAuthority('ROLE_XYZ')"), а в spring безопасность 4 @PreAuthorize("hasRole('XYZ')") совпадает с @PreAuthorize("hasAuthority('ROLE_XYZ')").

Относительно вашего варианта использования:

Пользователи имеют роли и роли, которые могут выполнять определенные операции.

Вы можете оказаться в GrantedAuthorities для ролей, к которым принадлежит пользователь, и операций, которые может выполнять роль. GrantedAuthorities для ролей имеет префикс ROLE_, а операции имеют префикс OP_. Примером для органов управления может быть OP_DELETE_ACCOUNT, OP_CREATE_USER, OP_RUN_BATCH_JOB и т.д. Ролями могут быть ROLE_ADMIN, ROLE_USER и т.д.

В результате вы можете реализовать свои объекты GrantedAuthority как в этом примере (псевдокод):

@Entity
class Role implements GrantedAuthority {
    @Id
    private String id;

    @OneToMany
    private final List<Operation> allowedOperations = new ArrayList<>();

    @Override
    public String getAuthority() {
        return id;
    }

    public Collection<GrantedAuthority> getAllowedOperations() {
        return allowedOperations;
    }
}

@Entity
class User {
    @Id
    private String id;

    @OneToMany
    private final List<Role> roles = new ArrayList<>();

    public Collection<Role> getRoles() {
        return roles;
    }
}

@Entity
class Operation implements GrantedAuthority {
    @Id
    private String id;

    @Override
    public String getAuthority() {
        return id;
    }
}

Ид ролей и операций, созданных в вашей базе данных, будет представлением GrantedAuthority, например. "ROLE_ADMIN", "OP_DELETE_ACCOUNT" и т.д. Когда пользователь аутентифицируется, убедитесь, что все GrantedAuthorities всех его ролей и соответствующие операции возвращены из метода UserDetails.getAuthorities().

Пример: Роль администратора с идентификатором ROLE_ADMIN имеет назначенные ему операции OP_DELETE_ACCOUNT, OP_READ_ACCOUNT, OP_RUN_BATCH_JOB. Роль пользователя с идентификатором ROLE_USER имеет операцию OP_READ_ACCOUNT.

Если в журнале администратора в результирующем контексте безопасности будут созданы функции GrantedAuthorities: ROLE_ADMIN, OP_DELETE_ACCOUNT, OP_READ_ACCOUNT, OP_RUN_BATCH_JOB

Если пользователь зарегистрирует его, он будет иметь: ROLE_USER, OP_READ_ACCOUNT

UserDetailsService позаботится о том, чтобы собрать все роли и все операции этих ролей и сделать их доступными методом getAuthorities() в возвращаемом экземпляре UserDetails.

Ответ 2

AFAIK GrantedAuthority и роли одинаковы в безопасности spring. GrantedAuthority getAuthority() - это роль (в соответствии с реализацией по умолчанию SimpleGrantedAuthority).

В вашем случае вы можете использовать иерархические роли

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
        class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_ADMIN > ROLE_createSubUsers
            ROLE_ADMIN > ROLE_deleteAccounts 
            ROLE_USER > ROLE_viewAccounts
        </value>
    </property>
</bean>

Не точный зол, который вы ищете, но надеюсь, что он поможет

Изменить: ответ на ваш комментарий

Роль подобна разрешению в spring -security. используя intercept-url with hasRole обеспечивает очень мелкий контроль над тем, какая операция разрешена для какой роли/разрешения.

Как мы обрабатываем в нашем приложении, мы определяем разрешение (то есть роль) для каждой операции (или URL-адрес отдыха), например. view_account, delete_account, add_account и т.д. Затем мы создаем логические профили для каждого пользователя, такие как admin, guest_user, normal_user. Профили - это просто логическая группировка разрешений, независимо от spring -security. Когда новый пользователь добавляется, ему присваивается профиль (имеющий все допустимые разрешения). Теперь, когда пользователь пытается выполнить какое-либо действие, разрешение/роль для этого действия проверяется на пользователя, предоставленномAuthorities.

Также по умолчанию в RoleVoter используется префикс ROLE_, поэтому любой авторитет, начинающийся с ROLE_, рассматривается как роль, вы можете изменить это поведение по умолчанию, используя пользовательский параметр RolePrefix в роли избирателя и используя его в безопасности spring.

Ответ 3

Еще один способ понять взаимосвязь между этими понятиями - это интерпретировать роль как контейнер полномочий.

Полномочия - это детализированные разрешения, нацеленные на конкретное действие в сочетании с определенной областью или контекстом данных. Например, Read, Write, Manage, могут представлять различные уровни разрешений для данного объема информации.

Кроме того, полномочия применяются глубоко в потоке обработки запроса, в то время как ROLE фильтруются путем фильтрации запросов до достижения Контроллера. Лучшие практики предписывают реализацию полномочий органов управления после Контроллера на бизнес-уровне.

С другой стороны, ROLES представляют собой грубое представление набора разрешений. ROLE_READER будет иметь только права на чтение или просмотр, а ROLE_EDITOR будет иметь права на чтение и запись. Роли в основном используются для первого просмотра на окраине обработки запроса, такого как HTTP....  .antMatcher(...). hasRole (ROLE_MANAGER)

Полномочия, применяемые глубоко в потоке обработки запросов, позволяют более детально применять разрешение. Например, пользователь может иметь разрешение на чтение и запись для первого уровня ресурса, но только для чтения на подресурс. Наличие ROLE_READER ограничило бы его право редактировать ресурс первого уровня, так как ему нужно разрешение на запись для редактирования этого ресурса, но перехватчик @PreAuthorize может заблокировать его предварительное редактирование подресурса.

Джейк