1. 概述
在本快速教程中,我們將探討如何在 Thymeleaf 中顯示已登錄用户的個人信息。
我們將擴展我們在 Spring Security 與 Thymeleaf 文章中構建的項目。首先,我們將添加一個自定義模型來存儲用户的信息,以及用於檢索這些信息的服務。之後,我們將使用 Thymeleaf Extras 模塊中的 Spring Security 語法的擴展功能來顯示它們。
2. UserDetails 實現
<em>UserDetails</em> 是 Spring Security 中的一個接口,用於存儲非安全相關的用户信息。
我們將創建 <em>UserDetails</em> 接口的實現,並添加一些自定義字段作為存儲認證用户詳細信息的模型。為了減少字段和方法的數量,我們將擴展默認框架的實現,即 <em>User</em> 類:
public class CustomUserDetails extends User {
private final String firstName;
private final String lastName;
private final String email;
private CustomUserDetails(Builder builder) {
super(builder.username, builder.password, builder.authorities);
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.email = builder.email;
}
// omitting getters and static Builder class
}3. 用户詳情服務實現
該框架的 <em UserDetailsService</em> 單方法接口負責在身份驗證過程中檢索 <em UserDetails</em>。
因此,為了能夠加載我們的 <em CustomUserDetails</em>,我們需要實現 <em UserDetailsService</em> 接口。 在我們的示例中,我們將硬編碼和存儲用户詳情到一個 <em Map</em> 中,其中用户名作為鍵:
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final PasswordEncoder passwordEncoder;
private final Map<String, CustomUserDetails> userRegistry = new HashMap<>();
// omitting constructor
@PostConstruct
public void init() {
userRegistry.put("user", new CustomUserDetails.Builder().withFirstName("Mark")
.withLastName("Johnson")
.withEmail("[email protected]")
.withUsername("user")
.withPassword(passwordEncoder.encode("password"))
.withAuthorities(Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")))
.build());
userRegistry.put("admin", new CustomUserDetails.Builder().withFirstName("James")
.withLastName("Davis")
.withEmail("[email protected]")
.withUsername("admin")
.withPassword(passwordEncoder.encode("password"))
.withAuthorities(Collections.singletonList(new SimpleGrantedAuthority("ROLE_ADMIN")))
.build());
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
CustomUserDetails userDetails = userRegistry.get(username);
if (userDetails == null) {
throw new UsernameNotFoundException(username);
}
return userDetails;
}
}此外,為了實現所需的 loadUserByUsername() 方法,我們從註冊表 Map 中通過用户名獲取相應的 CustomUserDetails 對象。但是,在生產環境中,用户詳情將存儲和從倉庫中檢索。
4. Spring Security 配置
首先,我們需要在 Spring Security 的配置中添加 UserDetailsService,該組件將連接到 CustomUserDetailsService 實現。 此外,我們將在 HttpSecurity 實例上通過相應的配置方法進行設置。 其餘的配置只是最小的安全配置,要求用户進行身份驗證,並配置 /login、/logout 和 /index 端點。
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
private final UserDetailsService userDetailsService;
// omitting constructor
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.userDetailsService(userDetailsService)
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
.anyRequest().authenticated())
.formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer
.loginPage("/login").permitAll()
.defaultSuccessUrl("/index"))
.logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.permitAll()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login"));
return http.build();
}
}5. 顯示已登錄用户的信息
Thymeleaf Extras 模塊提供對 Authentication 對象的訪問,以及藉助 Security Dialect,可以在 Thymeleaf 頁面上顯示已登錄用户的信息。
CustomUserDetails 對象可通過 principal 字段在 Authentication 對象中訪問。例如,我們可以使用 sec:authentication=”principal.firstName” 訪問 firstName 字段:
<!DOCTYPE html>
<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<title>Welcome to Spring Security Thymeleaf tutorial</title>
</head>
<body>
<h2>Welcome</h2>
<p>Spring Security Thymeleaf tutorial</p>
<div sec:authorize="hasRole('USER')">Text visible to user.</div>
<div sec:authorize="hasRole('ADMIN')">Text visible to admin.</div>
<div sec:authorize="isAuthenticated()">Text visible only to authenticated users.</div>
Authenticated username:
<div sec:authentication="name"></div>
Authenticated user's firstName:
<div sec:authentication="principal.firstName"></div>
Authenticated user's lastName:
<div sec:authentication="principal.lastName"></div>
Authenticated user's email:
<div sec:authentication="principal.lastName"></div>
Authenticated user roles:
<div sec:authentication="principal.authorities"></div>
</body>
</html>當然,以下是翻譯後的內容:
或者,可以使用 Spring 表達式語言編寫 Security Dialect 表達式,而無需使用 sec:authentication 屬性。因此,如果我們更習慣使用它,可以使用 Spring 表達式語言顯示 firstName 字段:
<div th:text="${#authentication.principal.firstName}"></div>6. 結論
在本文中,我們瞭解到如何使用 Spring Security 的支持,在 Spring Boot 應用程序中使用 Thymeleaf 顯示已登錄用户的個人信息。