1. 概述
本文將演示如何為 Spring Security 使用創建自定義數據庫支持的 <em >UserDetailsService</em> 進行身份驗證。
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. 檢索用户
為了檢索與用户名關聯的用户,我們將使用 DAO 類並使用 Spring Data 通過擴展 JpaRepository 接口:
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}5. 用户詳情服務 (UserDetailsService)
為了提供我們自己的用户服務,我們需要實現 UserDetailsService 接口。我們將創建一個名為 MyUserDetailsService 的類,並覆蓋接口中的 loadUserByUsername() 方法。
在該方法中,我們使用 DAO 獲取 User 對象,如果存在,則將其包裝成 MyUserPrincipal 對象,該對象實現了 UserDetails 接口,並返回它:
@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 註解配置
為了啓用我們自定義的 <em >UserDetailsService</em>,只需將其添加到我們的應用程序上下文作為 Bean 即可。
由於我們已使用 <em >@Service</em> 註解配置了我們的類,應用程序將在組件掃描期間自動檢測並將其創建為 Bean。因此,這裏無需我們做任何其他操作。
或者,我們可以:
- 使用 `AuthenticationManagerBuilder` 中的 `userDetailsService` 方法配置它
- 將其設置為自定義 `authenticationProvider` Bean 的屬性,然後使用 `AuthenticationManagerBuilder` 函數注入它
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 User Schema,則默認配置將適合我們。
我們在之前的文章中看到了使用這種方法進行的配置。
JdbcUserDetailsManager 實體,由此配置產生,也實現了UserDetailsService。
因此,我們可以得出結論,這種配置更容易實現,尤其當我們使用 Spring Boot 時,Spring Boot 會自動配置DataSource。
如果我們需要更高的靈活性,並且需要自定義應用程序如何檢索用户詳細信息,則我們會選擇我們在本教程中遵循的方法。
8. 結論
綜上所述,本文展示瞭如何創建基於 Spring 的自定義 UserDetailsService,並支持持久化數據。