Контроль доступа на основе разрешений весной

Я пытаюсь защитить свои конечные точки с помощью контроля доступа на основе ролей. Я реализовал всю структуру, а также CustomUserDetailService, однако я не уверен, как мне обеспечить соблюдение этих правил в точках, я искал какую-нибудь хорошую оценку на основе аннотаций, такую ​​как @PreAuthorize(hasRole('role')). Моя структура выглядит следующим образом:

Разрешение:

@Entity
public class Permission implements GrantedAuthority {

@Id
private Long id;

@Column(name = "NAME")
private String name;

@ManyToMany(mappedBy = "permissions",  fetch = FetchType.LAZY)
private Collection<Role> roles;

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

Роль:

@Entity
public class Role implements GrantedAuthority {

@Id @Column(name = "ID" )
private Long id;

@Column(name = "NAME", nullable=false , unique=false)
private String name;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
        name = "role_x_permission",
        joinColumns = @JoinColumn(
                name = "role_id"),
        inverseJoinColumns = @JoinColumn(
                name = "permission_id"))
private List<Permission> permissions;

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

Пользователь:

@Entity(name = "User")
@Table(name = "USERS")
@Data
public class User {

@Id
private Long id;

@Column(name = "LOGIN"   , nullable=true , unique=false)
private String login;

@Column(name = "PASSWORD"   , nullable=false , unique=false)
private String password;

@ManyToMany( fetch = FetchType.LAZY)
@JoinTable(name = "USER_ROLES",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;

Теперь я определил свой CustomUserDetailsService:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private UserRepository userRepository;


@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User applicationUser = userRepository.findByUsername(username);
    if (applicationUser.getId() == null) {
        throw new UsernameNotFoundException(username);
    }
    return new org.springframework.security.core.userdetails.User(applicationUser.getLogin(), applicationUser.getPassword(),
            getAuthorities(applicationUser.getRoles()));
}

@Transactional
public Collection<? extends GrantedAuthority> getUserAuthorities(String username) {
    User user = userRepository.findByUsername(username);

    return getAuthorities(user.getRoles());
}

private Collection<? extends GrantedAuthority> getAuthorities(
        Collection<Role> roles) {

    return getGrantedAuthorities(getPermissions(roles));
}

private List<String> getPermissions(Collection<Role> roles) {

    List<String> permissions = new ArrayList<>();
    List<Permission> collection = new ArrayList<>();
    for (Role role : roles) {
        collection.addAll(role.getPermissions());
    }
    for (Permission item : collection) {
        permissions.add(item.getName());
    }
    return permissions;
}

private List<GrantedAuthority> getGrantedAuthorities(List<String> permissions) {
    List<GrantedAuthority> authorities = new ArrayList<>();
    for (String permission : permissions) {
        authorities.add(new SimpleGrantedAuthority(permission));
    }
    return authorities;
}
}

Затем я пытаюсь аннотировать свою конечную точку с помощью @PreAuthorize

@PostMapping("/doSomething")
@PreAuthorize("hasRole('doSomething')")
public SomeEntity createComment(@RequestBody SomeEntity something) {
   ...
}

У меня есть пользователь с ролью USER, эта роль не имеет разрешения на doSomething, однако похоже, что @PreAuthorize("hasRole('doSomething')") не работает. Я не уверен, что я сделал не так, пожалуйста, укажите мою ошибку?

Кроме того, поскольку я использую RBAC, этот hasRole вводит в заблуждение, поскольку доступ основан на разрешениях, а не на ролях.

Каким будет правильный способ авторизации доступа к конечной точке с подходом RBAC?

Кроме того, поскольку я использую RBAC, этот hasRole очень ошибочен, поскольку доступ основан на разрешениях, а не на ролях. Это сбивает с толку, потому что RBAC означает Контроль доступа на основе ролей, а hasRole - правильный способ его реализации. Однако вы также не используете разрешения, потому что разрешения (формулировка Spring) являются частью ACL.
dur 22.11.2018 13:30

@dur позволяет предположить, что на данный момент это разрешение предназначено только для RBAC в моем случае. Если я правильно понял RBAC, каждая конечная точка может иметь разрешение, а роль имеет набор разрешений. Тогда hasRole нужно правильно ссылаться на разрешение?

Akka Jaworek 22.11.2018 14:00

Возможный дубликат stackoverflow.com/questions/44004977/…

dur 22.11.2018 21:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
1 725
1

Ответы 1

Вы должны использовать hasAuthority('doSomething') вместо hasRole('doSomething').

Роль - это просто разрешение с префиксом Role_.

Итак, hasRole('XXX') такой же, как hasAuthority('ROLE_XXX')

это не решило проблему, пользователь все еще может использовать doSomrthing

Akka Jaworek 22.11.2018 13:38

Другие вопросы по теме