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


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

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

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

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

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

Я тоже смотрю на 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)

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

3 167

3 ответа:

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

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

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

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

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

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

вы можете оказаться в GrantedAuthorities для ролей, к которым принадлежит пользователь, и операций, которые может выполнять роль. Элемент GrantedAuthorities для ролей есть префикс ROLE_ и операции имеют префикс OP_. Примером для оперативных органов может быть OP_DELETE_ACCOUNT,OP_CREATE_USER,OP_RUN_BATCH_JOB etc. Роли могут быть 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" и т. д. Когда пользователь проходит проверку подлинности, убедитесь, что все предоставленные полномочия всех его ролей и соответствующих операций возвращаются из 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.

AFAIK GrantedAuthority и роли одинаковы в spring security. Строка getAuthority () GrantedAuthority является ролью (согласно реализации по умолчанию 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>

Не точный sol вы ищете, но надеюсь, что это поможет

Edit: ответ на ваш комментарий

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

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

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

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

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

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

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

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

Джейк