Spring 启动 2.2.6 - 安全 |更新用户信息后如何更新Principal

Spring Boot 2.2.6 - Security | How to update Principal after updating user's information

在我的网站上,当用户登录时,他可以访问他的数据(密码、电子邮件...),并根据需要通过表单修改它们。处理数据并使用新数据更新数据库。但是,Spring(作为委托人)当前使用和保存的数据已经过时。我目前被迫断开用户连接,以便他再次连接自己以检索 "good" 数据,但这并不是真的......符合人体工程学。

如何 "refresh" 没有直接日志的 Principal 对象 out/in?

感谢您的帮助!

管理用户更新的控制器方法:

@RequestMapping(value = "/updateUser", method = RequestMethod.POST)
public ModelAndView updateProcess(Principal principal, HttpServletRequest request) {
    ModelAndView mv = new ModelAndView();
    updateUserService.updateUser(principal.getName(), request);
    if (updateUserService.getErrors().isEmpty()) {
        mv.setViewName("redirect:/deconnexion");
        mv.addObject("page", "index");
    } else {
        mv.setViewName("members/userUpdate");
        mv.addObject("page", "userProfile");
        mv.addObject("form", updateUserService);
    }
    return mv;
}

自己找到答案:

@RequestMapping(value = "/updateUser", method = RequestMethod.POST)
public ModelAndView updateProcess2(Authentication auth, HttpServletRequest request) {
    ModelAndView mv = new ModelAndView();
    PrincipalUser pu = (PrincipalUser) auth.getPrincipal();
    updateUserService.updateUser2(pu.getUser(), request);
    if (updateUserService.getErrors().isEmpty()) {
        mv.setViewName("members/userProfile");
        mv.addObject("page", "userProfile");
    } else {
        mv.setViewName("members/userUpdate");
        mv.addObject("page", "userProfile");
        mv.addObject("form", updateUserService);
    }
    return mv;
}

由于 Java 完全是关于引用的,直接更新主体对象转换为自定义 userDetails 将 "update" 它并阻止您记录 out/in 用户。

我的自定义 UserDetails class :

public class PrincipalUser implements UserDetails {
    private static final long serialVersionUID = 1L;

    //my personal User class
    private User user;

    public PrincipalUser(User user) {
        super();
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.singleton(new SimpleGrantedAuthority("USER"));
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getPseudo();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

所以我想一些通用代码应该是这样的:

@RequestMapping(value = "requestName", method = RequestMethod.POST)
public ModelAndView updateProcess(Authentication auth, HttpServletRequest request) {
    ModelAndView mv = new ModelAndView();
    //cast the Principal as your custom UserDetails
    CustomUserDetails cud = (CustomUserDetails) auth.getPrincipal();
    //ask a @Service class to process the new data and eventually update the user
    updateUserClass.updateUser(cud.whatYouNeed, request);
    //if no error while processing then set ModelAndView to your "succes page"
    if (updateUserClass.getErrors().isEmpty()) {
        mv.setViewName("successPage");
    } 
    //else set ModelAndView to your "form page" 
    //and, if you want, add the @Service class to show the
    //errors and other information in the form
    else {
        mv.setViewName("formPage");
        mv.addObject("form", updateUserClass);
    }
    return mv;
}