【发布时间】:2021-05-30 06:55:03
【问题描述】:
我在 Spring Boot 应用程序上实现 Authorities 时遇到了问题,经过一番挖掘后,我意识到我的 Credentials 和 Authorities 表之间的关联可能是错误的。
事实上,我注意到 Spring 允许所有类型的用户(无论他们的权限如何)访问任何方法,即使是我认为已经安全的方法。那时,我实现了一个.findAll() 方法来实际查看关联是否存在某种问题,并且确实存在。
让我先展示一下 MySQL 表:
CREATE TABLE credentials (
credential_id bigint UNSIGNED PRIMARY KEY AUTO_INCREMENT,
email varchar(50) NOT NULL UNIQUE,
password varchar(255) NOT NULL,
enabled BOOLEAN NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE authorities (
email varchar(50) NOT NULL,
authority varchar(50) NOT NULL,
PRIMARY KEY (email, authority),
CONSTRAINT fk_authorities_credentials FOREIGN KEY(email) REFERENCES credentials(email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
在跳转到实体中的关联之前,值得注意的是,权限实体具有反映表设计的嵌入键。所以email 列同时是一个foreign key 和一个主:
@Embeddable
public class AuthoritiesKey implements Serializable {
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "email", nullable = false
,referencedColumnName = "email")
private Credentials credentials;
@JoinColumn(name = "authority", nullable = false)
private String authority;
//getters setters omitted
}
凭证类:
@Entity
@Table(name = "credentials")
public class Credentials implements Serializable {
@OneToOne(cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
mappedBy = "ak.credentials")
private Authorities authorities;
//other fields and getters/setters omitted
}
删除双边关联(因此只保留在 AuthoritiesKey 类上),hibernate 成功返回所有凭据(当然没有他们的权限)和所有权限(这次是在凭据之前)。
我无法理解它。
当我离开双边关联时,我得到的完整有意义的堆栈跟踪如下:
Error accessing field [private java.lang.String com.server.model.Credentials.email] by reflection for persistent property [com.servermodel.Credentials#email] : 64;
nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.String com.server.model.Credentials.email] by reflection for persistent property [com.server.model.Credentials#email] : 64
其中 64 是 Credential 表中(最后一个,但被调用的第一个)行的 id。
=== 更新 ===
public class CredentialsService implements UserDetailsService {
@Autowired
private CredentialsRepository cr;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Credentials user = cr.findByEmail(email);
if (user == null){
throw new UsernameNotFoundException(email);
}
return new UserPrincipal(user);
}
}
【问题讨论】:
标签: java spring-boot hibernate spring-security spring-data-jpa