简体   繁体   中英

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

On my website when a user is logged in he can access his data (password, email...) and modify them if he wants via a form. The data are processed and the DB is updated with the new data. But, the data currently used and kept by Spring (as Principal) are outdated. I'm currently forced to disconnect the user so that he connects himself again to retrieve the "good" data but that's not really... ergonomic.

How can I "refresh" the Principal object without direct log out/in?

Thanks for your help !

Controller method managing user update:

@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;
}

Found an answer by myself: https://stackoverflow.com/a/7267941/12642186

@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;
}

Since Java is all about reference, directly updating the principal object cast as a custom userDetails will "update" it and prevent you from log out/in the user.

My custom 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;
    }
}

So I guess some generic code should looks like this:

@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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM