Spring Security з ролями та дозволами


77

Я намагаюся налаштувати рольову безпеку з дозволами. Я намагаюся зробити це разом із Spring-Security.

Я не хочу налаштовувати ACL, оскільки, здається, це надмірно для моїх вимог.

Я просто хочу мати прості дозволи та ролі, як описано в цій статті . На жаль, у статті не описано, як реалізувати дане рішення.

Хтось уже пробував це і може вказати мені в правильному напрямку? Можливо, є інший запис у блозі, який описує реалізацію?

Дуже дякую.


15
Для всіх, хто прибув сюди, є стаття, яка точно вирішує мою проблему. Будь ласка, подивіться на це
спалах

Я прочитав цю статтю, і я намагаюся це реалізувати. Скажіть, будь ласка, як ви реалізували клас SpringSecurityDaoImpl? @PreAuthorize взагалі не впливає на мої URL-адреси! Я зробив так само, як матеріал у цій статті.
sina

@sina Вам не потрібно реалізовувати SpringSecurityDaoImplпросто розширення, JdbcDaoImplяк у прикладі. Обов’язково перегляньте приклад коду на github, на який посилається стаття.
спалах

Відповіді:


32

Для реалізації цього, здається, вам потрібно:

  1. Створіть свою модель (користувач, роль, дозволи) та спосіб отримання дозволів для даного користувача;
  2. Визначте свій власний org.springframework.security.authentication.ProviderManagerта налаштуйте його (встановіть його провайдерів) на власний org.springframework.security.authentication.AuthenticationProvider. Цей останній повинен повернути для свого методу автентифікації аутентифікацію, яка повинна бути встановлена ​​з org.springframework.security.core.GrantedAuthorityусіма дозволами для даного користувача, у вашому випадку.

Фокус у цій статті полягає в тому, щоб призначити ролі користувачам, але встановити дозволи для цих ролей в Authentication.authoritiesоб’єкті.

Для цього я раджу вам прочитати API і подивитися, чи можете ви розширити деякі основні ProviderManager та AuthenticationProvider замість того, щоб реалізовувати все. Я зробив це, org.springframework.security.ldap.authentication.LdapAuthenticationProviderвстановивши власний LdapAuthoritiesPopulator, який отримував би правильні ролі для користувача.

Сподіваюся, цього разу я отримав те, що ти шукаєш. Удачі.


1
розширити цей DaoAuthenticationProvider і надати йому користувальницький UserDetailsService, який повинен виконувати завантаження дозволів.
ezequielb

78

Я автор статті, про яку йде мова.

Без сумніву, існує кілька способів зробити це, але я зазвичай це роблю, це реалізувати спеціальний, UserDetailsякий знає про ролі та дозволи. Roleі Permissionце лише власні класи, які ви пишете. (Нічого химерного - не Roleмає імені, і набору Permissionпримірників, і Permissionмає ім’я.) Потім getAuthorities()повертаються GrantedAuthorityоб’єкти, які виглядають так:

PERM_CREATE_POST, PERM_UPDATE_POST,PERM_READ_POST

замість повернення таких речей, як

ROLE_USER, ROLE_MODERATOR

Ролі все ще доступні, якщо у вашій UserDetailsреалізації є getRoles()метод. (Я рекомендую його мати.)

В ідеалі ви призначаєте ролі користувачеві, і відповідні дозволи заповнюються автоматично. Сюди входило б користувальницьке вміння, UserDetailsServiceяке знає, як виконати це зіставлення, і все, що йому потрібно зробити, - це джерело відображення з бази даних. (См. Статтю для схеми.)

Тоді ви можете визначити свої правила авторизації з точки зору дозволів, а не ролей.

Сподіваюся, що це допомагає.


1
Привіт, не могли б ви надати практичне рішення про користувацькі дані, як ви докладно описали у цій відповіді? Дякую.
rayman

Привіт, я реалізував додаток, використовуючи Spring Security, використовуючи власні класи AuthenticationProvider та UserDetailsService. Тепер я хочу використовувати ролі та дозволи в моїй програмі. Зараз я використовую це: @Secured ("ROLE_ADMIN") , який використовує дескриптори лише ролей. Як я розширюю це для обробки дозволів. (Детальніше тут -> stackoverflow.com/questions/23072619/… )
Kleber Mota

6

Основними кроками є:

  1. Використовуйте власний постачальник аутентифікації

    <bean id="myAuthenticationProvider" class="myProviderImplementation" scope="singleton">
    ...
    </bean>
    

  2. Зробіть так, щоб ваш спеціальний постачальник повернув власну UserDetailsреалізацію. Це UserDetailsImplматиме getAuthorities()приблизно таке:

    public Collection<GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> permissions = new ArrayList<GrantedAuthority>();
        for (GrantedAuthority role: roles) {
            permissions.addAll(getPermissionsIncludedInRole(role));
        }
        return permissions;
    }
    

Звичайно, звідси ви можете застосувати багато оптимізацій / налаштувань для своїх конкретних вимог.


5

Це найпростіший спосіб зробити це. Дозволяє повноваження групи, а також повноваження користувачів.

-- Postgres syntax

create table users (
  user_id serial primary key,
  enabled boolean not null default true,
  password text not null,
  username citext not null unique
);

create index on users (username);

create table groups (
  group_id serial primary key,
  name citext not null unique
);

create table authorities (
  authority_id serial primary key,
  authority citext not null unique
);

create table user_authorities (
  user_id int references users,
  authority_id int references authorities,
  primary key (user_id, authority_id)
);

create table group_users (
  group_id int references groups,
  user_id int referenecs users,
  primary key (group_id, user_id)
);

create table group_authorities (
  group_id int references groups,
  authority_id int references authorities,
  primary key (group_id, authority_id)
);

Потім у META-INF / applicationContext-security.xml

<beans:bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="passwordEncoder" />

<authentication-manager>
    <authentication-provider>

        <jdbc-user-service
                data-source-ref="dataSource"

                users-by-username-query="select username, password, enabled from users where username=?"

                authorities-by-username-query="select users.username, authorities.authority from users join user_authorities using(user_id) join authorities using(authority_id) where users.username=?"

                group-authorities-by-username-query="select groups.id, groups.name, authorities.authority from users join group_users using(user_id) join groups using(group_id) join group_authorities using(group_id) join authorities using(authority_id) where users.username=?"

                />

          <password-encoder ref="passwordEncoder" />

    </authentication-provider>
</authentication-manager>

1

Тільки заради повноти (можливо, комусь іншому не доведеться реалізовувати це з нуля):

Ми впровадили власну невелику бібліотеку, як і всі інші. Це повинно полегшити ситуацію, щоб нашим розробникам не доводилося щоразу виконувати це. Було б чудово, якби весняна безпека забезпечувала підтримку rbac нестандартно, оскільки такий підхід набагато кращий, ніж той, що базується на дозволі за замовчуванням.

Подивіться на Github (OSS, ліцензія MIT), щоб перевірити, чи відповідає він вашим потребам. В основному це стосується лише відображення привілеїв ролі <->. Відсутній фрагмент, який вам доведеться надати самостійно, - це в основному відображення ролей користувача <->, наприклад, шляхом зіставлення груп (racf / групи оголошень) з ролями (1: 1) або реалізацією додаткового відображення. Це різне в кожному проекті, тому немає сенсу надавати певну реалізацію.

Ми в основному використовували це внутрішньо, щоб ми могли починати з rbac з самого початку. Ми все ще можемо замінити його іншою реалізацією пізніше, якщо додаток зростає, але для нас важливо налаштувати одразу на початку.

Якщо ви не використовуєте rbac, є велика ймовірність, що дозволи розподілені по всій кодовій базі, і вам буде важко витягти / згрупувати їх (за ролями) пізніше. Сформовані графіки також допомагають міркувати про це / реструктурувати його пізніше.


1

ACL також був надмірним для моїх вимог.
У підсумку я створив бібліотеку, подібну до @ Alexander, щоб ввести GrantedAuthorityсписок для Ролі-> Дозволи на основі членства в ролі користувача.

Наприклад, використання БД для утримання відносин -

@Autowired 
RolePermissionsRepository repository;

public void setup(){
  String roleName = "ROLE_ADMIN";
  List<String> permissions = new ArrayList<String>();
  permissions.add("CREATE");
  permissions.add("READ");
  permissions.add("UPDATE");
  permissions.add("DELETE");
  repository.save(new RolePermissions(roleName, permissions));
}

Коли об’єкт автентифікації вводиться в поточний сеанс безпеки, він матиме початкові ролі / надані повноваження.

Ця бібліотека забезпечує 2 вбудовані точки інтеграції для Spring Security. Коли точка інтеграції досягнута, PermissionProvider викликається для отримання ефективних дозволів для кожної ролі, членом якої є користувач.
Окремий список дозволів додається як елементи GrantedAuthority в об'єкт автентифікації.

Ви також можете реалізувати спеціальний PermissionProviderдля зберігання відносин, наприклад, в config.

Більш повне пояснення тут - https://stackoverflow.com/a/60251931/1308685

А вихідний код тут - https://github.com/savantly-net/spring-role-permissions


0

Прочитавши цю публікацію , від Baeldung. Я виявив, що рішення досить просте.

Що я зробив, так це додати роль і дозволи до GrantedAuthority. Я зміг отримати доступ до обох методів hasRole () та hasAuthority ().

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.