在 Spring Security 中,将数据库中的用户信息集成到认证流程的核心在于实现 UserDetailsService 接口。这个接口负责从数据源加载用户详情,包括用户名、密码及权限信息。
要实现这一功能,我们需要完成三个主要环节:定义实体模型、编写加载逻辑的服务类,以及在安全配置中注册该服务。
1. 准备数据模型
首先,我们需要在持久层定义好用户与角色的实体关系。这里以 JPA 为例,User 实体存储基本信息,并通过多对多关联持有角色集合。
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@ManyToMany(fetch = FetchType.EAGER)
private Set<Role> roles;
// Getters and Setters omitted for brevity
}
角色实体相对简单,主要用于标识权限名称。
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Getters and Setters omitted for brevity
}
2. 实现 UserDetailsService
接下来是核心部分,创建一个实现了 UserDetailsService 接口的 Service 类。在这个类中,我们通过 Repository 查询数据库,并将查询结果转换为 Spring Security 所需的 UserDetails 对象。
需要注意的是,如果数据库中找不到对应用户,必须抛出 UsernameNotFoundException,否则框架无法正确处理认证失败的情况。
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails UsernameNotFoundException {
userRepository.findByUsername(username)
.orElseThrow(() -> ( + username));
.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
mapRolesToAuthorities(user.getRoles())
);
}
Collection<? > mapRolesToAuthorities(Collection<Role> roles) {
roles.stream()
.map(role -> (role.getName()))
.collect(Collectors.toList());
}
}

