0

Я проектирования модели БД, где я хочу иметь:Hibernate Spring безопасности изменен дизайн, как

  • пользователя (ID, ROLE_ID) (UserDetails)
  • Разрешение (ROLE_ID, разрешение) (GrantedAuthority)
  • Роль (идентификатор, описание)

Я использую Hibernate и Spring безопасности. Я хочу, чтобы у каждой роли был список разрешений (GrantedAuthorities) с использованием role_id, а не у конкретного пользователя. Я немного потерял разработку этого. Это то, к чему я пришел до сих пор:

Я опустил не очень важный код. Класс Role не важен для безопасности Spring.

Я знаю, что я совершаю огромную ошибку, но я просто не могу понять, как это исправить. Проблема в том, что он объединяет эти два объекта, используя user.id вместо user.roleId. Я пробовал разные аннотации, но я просто не могу правильно подключить их.

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

Редактировать: Я также попытался указать referColumnName в классе Permission, но это тоже не сработало. Пользователь не может войти в систему.

@ManyToOne(fetch = FetchType.EAGER) 
@JoinColumn(name = "role_id", nullable = false, insertable = false, updatable = false, referencedColumnName = "role_id") 
private User user; 
+0

Вы можете также предоставить схему сущности? Я не вижу, как разрешение сопоставляется с объектом User. Он должен быть обратным = true в пользовательском объекте, так как разрешение поддерживает отношения. – Zeus

+0

У меня нет диаграммы сущности, но я в значительной степени свободен, чтобы изменить ситуацию. Просто нужно как-то работать. Если я просто избегаю аннотаций и устанавливаю список разрешений вручную на основе role_id, пользователь работает правильно. – Lenymm

+0

Просто забудьте о коде. Как бы вы достигли системы, где пользователь имеет несколько разрешений, основанных на его роли? И он должен работать под управлением Spring, поэтому пользователь должен вернуть список разрешений. – Lenymm

ответ

1

Почему вы хотите иметь конструкцию, которая может иметь неприятные последствия вас в будущем? Вам действительно нужно думать заранее и применять хорошие методы проектирования в своем проекте. Этот вопрос появляется здесь почти каждый день.

В контексте весны роль на самом деле является авторитетом. Я понятия не имею, почему они сделаны настолько сложными по дизайну. У вас может быть 1) очень простой подход, когда вы назначаете роль, которая на самом деле является полномочием для пользователя или 2) более сложным решением, которое включает пользователя, Роль и Разрешение. Идея заключалась бы в том, чтобы назначать разрешения для ролей и назначать роли пользователю. В этом решении объект role предназначен только для группировки предоставленных разрешений вместе как один пакет, но через диспетчер проверки подлинности вы назначаете разрешениям через ролей.

Примечание: Я использую общую базу @MappedSuperclass для своих объектов.

Во-первых, есть объект пользователя:

@Entity 
@Table(name = "user_t") 
public class User extends BaseEntity { 

    @Column(name = "username", nullable = false, unique = true) 
    private String userName; 

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

    @ManyToMany 
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) 
    private Set<Role> role = new HashSet<Role>(); 

    // builder/getters/setters 
} 

Роль субъекта

@Entity(name = "role_t") 

    @Column(name = "role_name", nullable = false) 
    private String roleName; 

    @ManyToMany(fetch = FetchType.EAGER) 
    @JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "permission_id")) 
    private Set<Permission> permissions; 

    // getters/setters 
} 

Разрешение объект

@Entity(name = "permission_t") 
public class Permission extends BaseEntity implements GrantedAuthority { 

    @Column (name = "permission_name", nullable = false) 
    private String permissionName; 

    public String getPermissionName() { 
     return permissionName; 
    } 

    public void setPermissionName(String permissionName) { 
     this.permissionName = permissionName; 
    } 

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

    @Override 
    public int hashCode() { 
     return permissionName.hashCode(); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if(obj == null) return false; 
     if(!(obj instanceof Permission)) return false; 
     return ((Permission) obj).getAuthority().equals(permissionName); 
} 

Теперь в вашем AuthenticationManager или чем вы решите использовать, вы зацикливаете роли и назначаете разрешения, назначенные ролям пользователю, если это имеет смысл.

CustomAuthenticationProvider

public class AppAuthProvider implements AuthenticationProvider { 

    private static final String PERMISSION_PREFIX = "ROLE_PERMISSION_"; 
    // get the logging user info 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 


     Collection<GrantedAuthority> permissions = new HashSet<GrantedAuthority>(); 
     for (Role role : user.getRole()) { 
      for (Permission perm : role.getPermissions()) { 
       GrantedAuthority permission = new SimpleGrantedAuthority(PERMISSION_PREFIX + perm.getPermissionName()); 
       permissions.add(permission); 
      } 
     } 

     UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user, null, permissions); // user object you get from service/repository 

     return authToken; 
    } 
} 
+0

Это именно то, что я хочу продолжить. Роль будет мостом между пользователем, а роль разрешения не затрагивает меня в проверках разрешений в проекте. – Lenymm

0

Я думаю, что вам нужно пересмотреть свою схему, см. Изображение ниже. работа отсюда. Для сопоставления разрешений для роли вам нужна таблица со многими параметрами.

public class User implements UserDetails, Serializable { 

    @Id 
    @GeneratedValue 
    @Column(name = "id") 
    private int id; 
    @JoinColumn(name = "role_id", mappedBy= 'user", insertable = true, updatable = false) 
    private Role role;  

} 

public class Permission implements Serializable { 

    @Id 
    @GeneratedValue 
    @Column(name = "id") 
    private int id; 
    @Column(name = "permission") 
    private String permission; 
    @ManyToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL) 
    @JoinTable(name = "role_permissions", catalog = "schema", joinColumns = { 
     @JoinColumn(name = "id", nullable = false, updatable = false) }, inversJoinColumns = 
      { @JoinColumn(name = "id", nullable = false, updatable = false)} 
    private Set<Role> roles; 

    } 


public class Role implements Serializable { 

    @Id 
    @GeneratedValue 
    @Column(name = "id") 
    private int id; 
    @Column(name = "permission") 
    private String permission; 
    @ManyToMany(fetch=FetchType.LAZY, mappedBy = "permission") 
    public Set<Permissions> permisions; 
    } 

Обновление: см. Новую схему схемы.

Updated schema diagram

+0

У меня нет разрешения на имя пользователя, потому что я хочу получить систему, в которой пользователь имеет определенную роль, и эта роль указывает, какие права у пользователя есть. – Lenymm

+0

Yikes, мой плохой, используйте role_id внутри пользователя. Или создать другой объект role_user, который имеет сопоставление пользователя с ролью. – Zeus

+0

Должен ли я? Не существует способа сопоставить его с пользователем с ролью? Я имею в виду, что у пользователя будет только одна роль, а одна роль будет иметь список разрешений. Создание другого объекта просто для сопоставления пользователя с ролью не похоже на это. – Lenymm

Смежные вопросы