1. 概述
在这篇文章中,我们将展示如何使用Spring Security创建一个自定义的数据库支持的UserDetailsService
进行身份验证。
2. UserDetailsService
UserDetailsService
接口用于检索与用户相关的信息。它有一个名为 loadUserByUsername()
的方法,可以重写以自定义查找用户的过程。
DaoAuthenticationProvider
在身份验证过程中使用它来加载用户的详细信息。
3. 用户模型
为了存储用户,我们将创建一个名为 User
的实体,它映射到数据库表,具有以下属性:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false, unique = true)
private String username;
private String password;
// standard getters and setters
}
4. 获取用户
为了根据用户名获取用户,我们将使用 Spring Data 创建一个 DAO
类,扩展 JpaRepository
接口:
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
5. UserDetailsService
为了提供我们自己的用户服务,我们需要实现 UserDetailsService
接口。
我们将创建一个名为 MyUserDetailsService
的类,重写接口中的 loadUserByUsername()
方法。
在这个方法中,我们使用 DAO
获取 User
对象,如果存在,我们将它包装到一个实现了 UserDetails
的 MyUserPrincipal
对象中,并返回:
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
}
return new MyUserPrincipal(user);
}
}
让我们定义 MyUserPrincipal
类如下:
public class MyUserPrincipal implements UserDetails {
private User user;
public MyUserPrincipal(User user) {
this.user = user;
}
//...
}
6. Spring 配置
我们将演示两种类型的Spring配置:基于注解和XML配置,这是使用我们自定义的 UserDetailsService
实现所必需的。
6.1. 注解配置
为了启用我们的自定义 UserDetailsService
,只需将其作为bean添加到我们的应用程序上下文中即可。
由于我们使用了 @Service
注解配置了类,应用在组件扫描期间会自动检测到它,并会将这个类转换为一个bean。所以在这里我们不需要做其他事情。
或者,我们可以:
- 使用
AuthenticationManagerBuilder#userDetailsService
方法将它配置到authenticationManager
- 将其设置为自定义
authenticationProvider
的属性,然后使用AuthenticationManagerBuilder#authenticationProvider
函数注入
6.2. XML配置
对于XML配置,我们需要定义一个类型为 MyUserDetailsService
的bean,并将其注入Spring的 authentication-provider
bean:
<bean id="myUserDetailsService"
class="org.baeldung.security.MyUserDetailsService"/>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="myUserDetailsService" >
<security:password-encoder ref="passwordEncoder">
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="passwordEncoder"
class="org.springframework.security
.crypto.bcrypt.BCryptPasswordEncoder">
<constructor-arg value="11"/>
</bean>
7. 其他基于数据库的身份验证选项
AuthenticationManagerBuilder
提供了另一种方法来在我们的应用中配置基于JDBC的身份验证。
我们需要使用 AuthenticationManagerBuilder.jdbcAuthentication
配置一个 DataSource
实例。如果我们的数据库遵循 Spring Security的用户模式,那么默认配置将非常适合我们。
我们在之前的文章中已经看到了使用这种方法的基本配置。
这种配置产生的 JdbcUserDetailsManager
实体也实现了 UserDetailsService
。
因此,我们可以得出结论,这种配置更容易实现,特别是如果我们正在使用Spring Boot,它会自动为我们配置 DataSource
。
如果我们确实需要更高的灵活性,精确控制应用程序如何获取用户详细信息,那么我们将选择本教程中介绍的方法。
8. 总结
总之,本文展示了如何创建一个基于持久数据的Spring自定义 UserDetailsService
。
实现代码可以在 GitHub项目 中找到 - 这是一个基于Maven的项目,可以直接导入并运行,因为它是现成的。