根据Spring文档,如果您需要通过数据库管理spring安全性,那么您应该有一些标准的表模式。例如。
create table users(
username varchar(256) not null primary key,
password varchar(256) not null,
enabled boolean not null
);
create table authorities (
username varchar(256) not null,
authority varchar(256) not null,
constraint fk_authorities_users foreign key(username) references users(username)
);
create unique index ix_auth_username on authorities (username,authority);
我面临的问题是如下。 1)无法理解如何使用JPA实现这种表格模式?
我尝试了以下内容。
@Entity
@Table(name="USERS")
public class UsersPersistence extends Users implements Serializable{
private static final long serialVersionUID = 1009548075747154488L;
public UsersPersistence() {
super();
}
public UsersPersistence(long id, String userName, String password, boolean enabled) {
super(id, userName,password,enabled);
}
@Id
@GeneratedValue
@Column(name="id")
@Override
public long getId() {
return super.getId();
}
@Column(name="username", nullable=false)
@Override
public String getUserName() {
return super.getUserName();
}
@Column(name="password", nullable=false)
@Override
public String getPassword() {
return super.getPassword();
}
@Column(name="enabled", nullable=false)
@Override
public boolean isEnabled() {
return super.isEnabled();
}
}
此表根据Spring文档架构中声明的要求创建。 理解的问题是当我试图在权限表中的用户名上分配外键时。由于JPA通过父表的id(主键表)分配外键,或者可能是我不知道如何分配它。
以下是产生问题的JPA类: -
@Entity
@Table(name="AUTHORITIES")
public class AuthoritiesPersistence extends Authorities implements Serializable{
private static final long serialVersionUID = 1L;
public AuthoritiesPersistence() {
super();
}
public AuthoritiesPersistence(long id, UsersPersistence userName, String authority) {
super(id,userName,authority);
}
@Id
@GeneratedValue
@Column(name="id")
@Override
public long getId() {
return super.getId();
}
@Override
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="username", nullable=false)
public UsersPersistence getUserName() {
return (UsersPersistence) super.getUserName();
}
@Column(name="authority", nullable=false)
@Override
public String getAuthority() {
return super.getAuthority();
}
}
此表已成功创建,但Spring安全身份验证无法识别用户名,因为JPA使用外键ID而非实际用户名。
任何帮助都会很明显。我真的很难创建一个基于用户名而不是id的外键。 谢谢
答案 0 :(得分:2)
当使用默认JdbcDaoImpl
作为UserDetailsService
实现时,您只需坚持Spring安全参考文档中给出的模式,如果您有<jdbc-user-service>
标记,就是这种情况你的安全配置。即使这样,也可以覆盖用于获取用户和权限的默认SQL查询(请参阅namespace appendix)。
但是,如果您使用hibernate管理用户帐户,则编写自己的UserDetailsService
实现是有意义的,而不是尝试创建导致JdbcDaoImpl
所需的特定架构的JPA实体。 / p>
如果您的应用程序确实使用了ORM工具,您可能更愿意编写自定义UserDetailsService来重用您可能已经创建的映射文件。
答案 1 :(得分:1)
有几种方法可以解决这个问题:
<jdbc-user-service>
并覆盖@zagyi提到的SQL查询。 (http://static.springsource.org/spring-security/site/docs/current/reference/appendix-namespace.html#nsa-jdbc-user-service)<jdbc-user-service>
要使用您感兴趣的方法,您必须知道除了字段用户名,密码和启用的spring安全性之外,用户名必须是唯一标识符。这意味着您可以将实体的username属性用作数据库和Hibernate的Id。 如果你不想这样做,那么接近这个就是设置一个表,用一个ID / Name和权限来定义授权。然后设置使用jointable将它们映射到用户。 一些未经测试的示例代码: 的作用:强>
@Entity
@DynamicUpdate
@Table(name ="authorities")
public class Authority{
private String authority;
@Id
@Column(name="authority")
public String getAuthority() {
return authority;
}
用户:强>
@Entity
@DynamicUpdate
@Table(name = "users", uniqueConstraints={ @UniqueConstraint(columnNames={"username"})})
public class User {
private String username;
private List<Authority> authorities;
@Type(type = "numeric_boolean")
private boolean enabled;
@Id
@Column(name="username")
public String getUsername() {
return username;
}
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "authorities",
joinColumns = @JoinColumn(name = "username"),
inverseJoinColumns = @JoinColumn(name = "rolename")
)
public List<Authority> getauthorities() {
return authorities;
}
@Column(name="ENABLED")
public boolean isEnabled() {
return enabled;
}
当基地运行时,您可以添加内部使用的属性。
答案 2 :(得分:0)
我已经找出了“配置JdbcUserDetailsManager以使用自定义SQL查询”的替代方案,至少我可以通过JPA创建我的表并且可以希望 “user-by-username-query和authority-by-username-query”确实可以完成我的工作。 为了实现它,我必须添加以下模式。
create table custom_user_authorities (
id bigint identity,
user bigint not null,
authority varchar(256) not null,
);
此架构具有id(将自动递增),这肯定适用于JPA。
答案 3 :(得分:0)
我能够使用以下类定义映射这些表:
@Entity
@Table(name = "users")
public class User {
@Id
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column
private boolean enabled;
@Column
private String firstName;
@ElementCollection
@JoinTable(name = "authorities", joinColumns = {@JoinColumn(name = "email")})
@Column(name = "authority")
private Set<String> roles;
public User() {
}
public Serializable getId() {
return username;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void setPassword(String password) {
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
}