如何使用 Spring Boot Thymeleaf 显示当前登录的用户?

Posted

技术标签:

【中文标题】如何使用 Spring Boot Thymeleaf 显示当前登录的用户?【英文标题】:How can I display the current logged in User with Spring Boot Thymeleaf? 【发布时间】:2018-06-29 17:17:26 【问题描述】:

我正在尝试显示当前用户的详细信息,但我不断收到错误消息。我尝试从模板访问经过身份验证的用户,但由于我收到此错误而不起作用:

在 org.springframework.security.core.userdetails.User 类型上找不到方法 getFirstName()

我试图从控制器获取信息,然后将其保存在字符串中并将字符串传递给模板,但这也不起作用。

这是我的 SecurityConfig 类:

    @Configuration
 public class SecurityConfig extends WebSecurityConfigurerAdapter 

@Autowired
private UserService userService;

@Override
protected void configure(HttpSecurity http) throws Exception 
    http
            .authorizeRequests()
                .antMatchers(
                        "/registration",
                        "/js/**",
                        "/css/**",
                        "/img/**",
                        "/webjars/**").permitAll()
                .anyRequest().authenticated()
            .and()
                .formLogin()
                    .loginPage("/login")
                        .permitAll()
            .and()
                .logout()
                    .invalidateHttpSession(true)
                    .clearAuthentication(true)
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/login?logout")
            .permitAll();


@Bean
public BCryptPasswordEncoder passwordEncoder()
    return new BCryptPasswordEncoder();


@Bean
public DaoAuthenticationProvider authenticationProvider()
    DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
    auth.setUserDetailsService(userService);
    auth.setPasswordEncoder(passwordEncoder());
    return auth;


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.authenticationProvider(authenticationProvider());


这是我的 UserService 类:

 public interface UserService extends UserDetailsService 

User findByEmailAddress(String emailAddress);
  //  User findByFirstName(String firstName);

User save(UserRegistrationDto registration);

这是我的 UserServiceImpl 类:

 @Service
public class UserServiceImpl implements UserService 

@Autowired
private UserRepository userRepository;

@Autowired
private BCryptPasswordEncoder passwordEncoder;

@Override
public UserDetails loadUserByUsername(String emailAddress) throws 
UsernameNotFoundException 
    User user = userRepository.findByEmailAddress(emailAddress);
    if (user == null)
        throw new UsernameNotFoundException("Invalid username or 
password.");
    
    return new 
org.springframework.security.core.userdetails.User(user.getEmailAddress(),
            user.getPassword(),
            mapRolesToAuthorities(user.getRoles()));


public User findByEmailAddress(String emailAddress)
    return userRepository.findByEmailAddress(emailAddress);


public User save(UserRegistrationDto registration)
    User user = new User();
    user.setFirstName(registration.getFirstName());
    user.setSurname(registration.getSurname());
    user.setEmailAddress(registration.getEmailAddress());
    user.setPassword(passwordEncoder.encode(registration.getPassword()));
    user.setRoles(Arrays.asList(new Role("ROLE_USER")));
    return userRepository.save(user);


private Collection<? extends GrantedAuthority> 
mapRolesToAuthorities(Collection<Role> roles)
    return roles.stream()
            .map(role -> new SimpleGrantedAuthority(role.getName()))
            .collect(Collectors.toList());




这是我试图获取信息的模板类中的一些代码:

th:text ="$#authentication.getPrincipal().getFirstName()">

th:text ="$#authentication.getPrincipal().getUser().getFirstName()">

这是登录控制器。我注释掉的部分是我试图获取当前用户详细信息的另一种方式:

@Controller
//@RequestMapping("/login")
public class MainController 

//    @GetMapping("/")
//    public String root() 
//        return "userProfile1";
//    

@GetMapping("/login")
public String login(Model model) 
    return "login";



 //   @GetMapping
  //  public String displayUserAccount(@ModelAttribute("user") @Valid             
UserRegistrationDto userDto, BindingResult result, Model model) 
//    
// 
//      model.addAttribute("firstName", ((UserRegistrationDto)         
auth).getEmailAddress());
//      
//      model.addAttribute("emailAddress", userDto.getEmailAddress());
//        model.addAttribute("firstName", userDto.getFirstName());
//        model.addAttribute("surname", userDto.getSurname());
//        model.addAttribute("age", userDto.getAge());
//        model.addAttribute("gender", userDto.getGender());
//        model.addAttribute("dob", userDto.getDob());
//       // return "redirect:/registration?success";
  //  return "userProfile1";
//      
  //  

@ResponseBody
public String currentUserName(Authentication auth) 
    ((UserRegistrationDto) auth).getEmailAddress();
    return  "userProfile1";





   

这里到处都是对不起!非常感谢任何帮助的人:D

【问题讨论】:

【参考方案1】:

您可以使用 Thymeleaf extras 来显示经过身份验证的用户详细信息。

Thymeleaf Extras Springsecurity4

    <div th:text="$#authentication.name ></div>

【讨论】:

【参考方案2】:

问题出在这里:

return new 
org.springframework.security.core.userdetails.User(user.getEmailAddress(),
        user.getPassword(),
        mapRolesToAuthorities(user.getRoles()));

您丢失了对您的 User 实体的引用。将其更改为:

return user;

为此,您需要更新您的User 实体以实现UserDetails 接口:

public class User implements UserDetails 
    // some new methods to implement

然后,您的 Thymleaf 代码应该可以工作了。获取firstName 的另一种方法是:

<span th:text="$#request.userPrincipal.principal.firstName"></span>

【讨论】:

感谢您的回复。不幸的是,当我删除第一段代码并将其更改为返回用户时,它并没有让我登录并说密码错误。 什么是 userPrincipal @Amare 在使用 Spring Security 时,“userPrincipal”是Authentication 对象。 你是怎么发现它可以这样使用的?【参考方案3】:

参考(4. Spring Security 方言):

https://www.thymeleaf.org/doc/articles/springsecurity.html

添加依赖 pom.xml

<dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>

和视图(Thymeleaf):

<div sec:authorize="isAuthenticated()"> 
    Authenticated user roles:
    Logged user: <span sec:authentication="name"></span> |
    Roles: <span sec:authentication="principal.authorities"></span>
</div>

我希望你为他们服务

【讨论】:

我遵循了官方的 Spring 示例,它使用与您完全相同的方法和语法。 github.com/spring-projects/spring-security/tree/master/samples/… 但是由于某种原因,这对我不起作用。用户和角色都是空白的,所以它显示“用户:|角色:”知道为什么吗?【参考方案4】:

我想出了如何解决我的问题。

我在控制器中创建了这个方法:

  @Autowired
UserRepository userR;
@GetMapping
public String currentUser(@ModelAttribute("user") @Valid UserRegistrationDto userDto, BindingResult result, Model model) 

    Authentication loggedInUser = SecurityContextHolder.getContext().getAuthentication();
    String email = loggedInUser.getName(); 

     User user = userR.findByEmailAddress(email);
    String firstname = user.getFirstName();
     model.addAttribute("firstName", firstname);
    model.addAttribute("emailAddress", email);

    return "userProfile1"; //this is the name of my template

然后我在我的 html 模板中添加了这行代码:

电子邮件:th:text="$emailAddress"

【讨论】:

在您询问用户实体中的 firstName 的问题中,这会显示 username 是的,我知道这一点,但我很高兴获得登录用户的任何详细信息。我将在一秒钟内更新我的答案。【参考方案5】:

您可以从 Principal 类中轻松获取用户名属性。

@GetMapping(value = "/")
    public String index(@AuthenticationPrincipal MyUserPrincipal principal) 
        String username = principal.getUsername();
        //Do whatever you want here
        return "index";
    

但是,如果您想要比 Principal 类中的更多详细信息,那么您需要在您的 Principal 类中明确定义它们:

public int getId() 
    return member.getId();

所以现在你可以直接调用它了:

@GetMapping(value = "/")
    public String index(@AuthenticationPrincipal MyUserPrincipal principal) 
        int userId = principal.getId();
        //Do whatever you want here
        return "index";
    

您需要导入以下内容:

import org.springframework.security.core.annotation.AuthenticationPrincipal;

如果您只想直接从 Thymeleaf 获取 Principal 类属性,那么您也可以执行以下操作:

<span sec:authentication="principal.username">Username</span>

【讨论】:

以上是关于如何使用 Spring Boot Thymeleaf 显示当前登录的用户?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 graphql-spring-boot 向 GraphQL Java 添加检测?

如何在 spring-boot 中禁用 spring-data-mongodb 自动配置

spring-boot如何使用两个DataSource

如何从另一个新的 Spring Boot 项目调用一个 Spring Boot 项目中存在的 Spring Boot api

如何在没有spring-boot的情况下使用eureka+feign?

如何在 Spring Boot 中使用 @Transactional 注解