[英]How can I get the currently logged in user's data in Spring Boot Thymeleaf?
我希望我的登錄用戶能夠看到他們自己的用戶個人資料,甚至可以根據需要進行修改。
我存儲用戶數據的兩個實體:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue
private Long id;
@Column(unique = true, nullable = false)
private String email;
@Column(nullable = false)
private String password;
private String fullName;
private String activation;
private Boolean enabled;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "users_roles", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = {
@JoinColumn(name = "role_id") })
private Set<Role> roles = new HashSet<Role>();
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private UserProfile userProfile;
//constructors, getters and setters
和:
@Entity
@Table(name="profiles")
public class UserProfile {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
@Column(length = 20)
private String activation;
@Column(length = 64)
private String address;
@Column(length = 32)
private String phoneNumber;
@Column(length = 60)
private String resetToken;
@OneToOne
private User user;
//constructors, getters and setters
我在我的 UserController 中寫了這個:
@GetMapping("/profile")
public String showUserProfile (Model model){
//Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//String currentPrincipalName = authentication.getName();
//User user = userRepository.findByEmail(authentication.getPrincipal());
//model.addAttribute("currentUser", user);
return "profile";
}
我在 UserRepository 和 UserService 中的 findByEmail 方法:
User findByEmail(String email);
STS 想將此方法修改為(對象主體)或類似的東西,但我無法更改它,因為該方法已被使用。
java.lang.Error: Unresolved compilation problem:
The method findByEmail(String) in the type UserRepository is not applicable for the arguments (Object)
對不起,我還是 Spring Boot 的新手。 如何獲取當前用戶的數據? 我已經做了一個用戶 CRUD,我想對當前用戶做同樣的事情,而不需要 DELETE 和 CREATE。
為了使用 spring-security 你必須實現 UserDetails 像:
public class UserPrincipal implements UserDetails {
private User user;
private String name;
private long uid;
public long getUid() {
return uid;
}
public void setUid(long uid) {
this.uid = uid;
}
public UserPrincipal(User user) {
this.user = user;
this.name = user.getName();
this.uid = user.getUid();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return "ROLE_USER";
}
});
return authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getEmail();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
還有這樣的服務:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email);
if(user == null) {
throw new UsernameNotFoundException("User Not found");
}
return new UserPrincipal(user);
}
}
然后添加獲取當前登錄用戶:
private UserPrincipal getLoggedInUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return (UserPrincipal)authentication.getPrincipal();
}
內部 UserPricipal object 存儲配置文件並在 thymeleaf 中訪問它。
要使用 Spring Security 和 Thymeleaf,您需要編寫實現UserDetails
的 class 。 這個 class 是您的應用程序和 Spring 安全性之間的“橋梁”。 它可能看起來像這樣:
public class ApplicationUserDetails implements UserDetails {
public ApplicationUserDetails(User user) {
this.username = user.getEmail();
this.password = user.getPassword(); //<.>
this.authorities = user.getRoles().stream()
.map(userRole -> new SimpleGrantedAuthority("ROLE_" + userRole.name()))
.collect(Collectors.toSet());
}
}
接下來,您需要編寫UserDetailsService
的實現。 此 class 將由 Spring 安全性調用,以了解哪個用戶 object 對應於給定的用戶名(或 Z0C83F57C7873A0B4A39EFAB2 用戶名而不是用戶名)。 所以是這樣的:
@Service
@Transactional(readOnly = true)
public class DatabaseUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public DatabaseUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException(
format("User with email %s could not be found", username)));
return new ApplicationUserDetails(user);
}
}
您還需要通過WebSecurityConfigurerAdapter
實現正確配置 Spring 安全性:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final PasswordEncoder passwordEncoder;
private final UserDetailsService userDetailsService;
public WebSecurityConfiguration(PasswordEncoder passwordEncoder,
UserDetailsService userDetailsService) {
this.passwordEncoder = passwordEncoder;
this.userDetailsService = userDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/img/*").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout().permitAll();
}
}
您現在可以使用 Spring 安全 Thymeleaf 集成來顯示登錄用戶的信息。
<span sec:authentication="name">Bob</span>
See https://www.thymeleaf.org/doc/articles/springsecurity.html for the docs or https://github.com/wimdeblauwe/taming-thymeleaf-sources/tree/main/chapter14 for a full Spring Boot project that展示了這一切。
我認為您的 findByEmail 方法是正確的。 您只需要更新如何獲取當前用戶 email。 您可以通過修改如何從安全上下文中獲取用戶 email 來獲得,如下所示
SecurityContextHolder.getContext().getAuthentication().getPrincipal.toString()
因為通過這種方式,它將返回主體的字符串值,在您的情況下將為 email。 但是現在它返回 Principal Object ,這就是 STS 抱怨將方法簽名修改為 (object principal) 的原因,正如您所提到的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.