簡體   English   中英

如何在 Spring Boot Thymeleaf 中獲取當前登錄用戶的數據?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM