gpt4 book ai didi

java - 如何使用 Hibernate/JPA 2 实现 Spring Security 用户/权限?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:47:33 25 4
gpt4 key购买 nike

我正在尝试实现 DAO 以在 Hibernate/JPA2 中使用 Spring Security 数据库身份验证。 Spring 使用以下关系和关联来表示用户和角色:

alt text

表示为 postgresql 创建查询:

CREATE TABLE users
(
username character varying(50) NOT NULL,
"password" character varying(50) NOT NULL,
enabled boolean NOT NULL,
CONSTRAINT users_pkey PRIMARY KEY (username)
);
CREATE TABLE authorities
(
username character varying(50) NOT NULL,
authority character varying(50) NOT NULL,
CONSTRAINT fk_authorities_users FOREIGN KEY (username)
REFERENCES users (username) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);

使用 GrantedAuthoritiesUserDetailsS​​erviceUserDetailsmanager 的板载实现,一切都很好。但是,我对Spring的JDBC实现不满意,想自己写一个。为此,我尝试通过以下业务对象来创建关系的表示:

用户实体:

@Entity
@Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"username"})})
public class AppUser implements UserDetails, CredentialsContainer {

private static final long serialVersionUID = -8275492272371421013L;

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

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

@OneToMany(
fetch = FetchType.EAGER, cascade = CascadeType.ALL,
mappedBy = "appUser"
)
private Set<AppAuthority> appAuthorities;

@Column(name = "accountNonExpired")
private Boolean accountNonExpired;

@Column(name = "accountNonLocked")
private Boolean accountNonLocked;

@Column(name = "credentialsNonExpired")
private Boolean credentialsNonExpired;

@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "personalinformation_fk", nullable = true)
@JsonIgnore
private PersonalInformation personalInformation;

@Column(name = "enabled", nullable = false)
@NotNull
private Boolean enabled;

public AppUser(
String username,
String password,
boolean enabled,
boolean accountNonExpired,
boolean credentialsNonExpired,
boolean accountNonLocked,
Collection<? extends AppAuthority> authorities,
PersonalInformation personalInformation
) {
if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
}

this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.appAuthorities = Collections.unmodifiableSet(sortAuthorities(authorities));
this.personalInformation = personalInformation;
}

public AppUser() {
}

@JsonIgnore
public PersonalInformation getPersonalInformation() {
return personalInformation;
}

@JsonIgnore
public void setPersonalInformation(PersonalInformation personalInformation) {
this.personalInformation = personalInformation;
}

// Getters, setters 'n other stuff

以及作为 GrantedAuthorities 实现的授权实体:

@Entity
@Table(name = "authorities", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class AppAuthority implements GrantedAuthority, Serializable {
//~ Instance fields ================================================================================================

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", nullable = false)
private Integer id;

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

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

// Here comes the buggy attribute. It is supposed to repesent the
// association username<->username, but I just don't know how to
// implement it
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "appuser_fk")
private AppUser appUser;

//~ Constructors ===================================================================================================

public AppAuthority(String username, String authority) {
Assert.hasText(authority,
"A granted authority textual representation is required");
this.username = username;
this.authority = authority;
}

public AppAuthority() {
}

// Getters 'n setters 'n other stuff

我的问题是 @ManyToOne 关联。 AppAuthorities:它应该是“用户名”,但尝试这样做会引发错误,因为我必须将该属性典型化为 String ... 而Hibernate 需要关联的实体。所以我尝试的实际上是提供正确的实体并通过 @JoinColumn(name = "appuser_fk") 创建关联。这当然是垃圾,因为为了加载用户,我将在 username 中拥有外键,而 Hibernate 在 appuser_fk 中搜索它,这将始终是空的。

所以这是我的问题:关于如何修改上述代码以获得数据模型的正确 JPA2 实现的任何建议?

谢谢

最佳答案

AppAuthority 根本不需要用户名。 Spring Security 不能依赖它,因为它依赖于 GrantedAuthority interface它没有任何访问用户名的方法。

但更好的做法是将您的域模型与 Spring Security 分离。当您拥有自定义 UserDetailsS​​ervice 时,您不需要模仿 Spring Security 的默认数据库架构及其对象模型。您的 UserDetailsS​​ervice 可以加载您自己的 AppUserAppAuthority,然后创建 UserDetailsGrantedAuthority基于它们。这导致更简洁的设计和更好的关注点分离。

关于java - 如何使用 Hibernate/JPA 2 实现 Spring Security 用户/权限?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3696680/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com