How to get user id with Spring MVC?

Tags: , ,



I using the POST method for add Item to the database with Spring MVC. But each Item has field userId, it FOREIGN KEY to users table. Need to know user’s id for this. I using Spring security for auth. May be there is a possibility get current user’s id with ServletContext or HttpSession, may be spring security save user’s id somewhere?

How to identify user which requested to the server with Spring MVC to data in the database?

@PostMapping("/get_all_items/add_item_page/add_item")
public String addItem(@RequestParam(value = "description")
                          final String description) {

    final Item item = new Item();

    item.setDescription(description);

    item.setAuthorId(/* ??? */);

    service.add(item);

    return "redirect:get_all_items";
}

Spring security implementation with using UserDetails so all details hidden from me, and I don’t know how to intervene in auth process and intercept user’s id in the authorysation stage.

@Entity(name = "users")
public class User implements UserDetails {...}

@Autowired
private UserService userService;

@Autowired
private void configureGlobal(AuthenticationManagerBuilder auth)
        throws Exception {

    auth.userDetailsService(userService);
}

Thank You!

Answer

Please try with this approach

Make sure that you have your own User pojo class

  @Entity
  public class MyUser {

    @Id
    private Long id;
    private String username;
    private String password;
    private boolean isEnabled;

    @ManyToMany
    private List<MyAuthority> myAuthorities;
    ...
  }

Also an Authority pojo in order to define the user roles

@Entity
public class MyAuthority {

    @Id
    private int id;

    private String name; .....

Then the user repository, in this example I just declare a method to find by username and get an Optional to validate if the user exists.

public interface MyUserRepository extends CrudRepository<MyUser,Long> {
    public Optional<MyUser> findFirstByUsername(String username);
}

Create a user class that extends from org.springframework.security.core.userdetails.User in order to wrap your custom user inside the definition of the spring security user.

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
public class MySpringUser  extends User {

    private MyUser user;

    public MySpringUser(MyUser myUser, Collection<? extends GrantedAuthority> authorities) {
        super(myUser.getUsername(), myUser.getPassword(), myUser.isEnabled()
                , true, true, true, authorities);
        this.setUser(myUser);   
    }

    public MyUser getUser() {
        return user;
    }

    public void setUser(MyUser user) {
        this.user = user;
    }
}

And now the UserDetailService implementation, there is just one method to implement loadUserByUsername here is where the MyUserRepository is needed, in order to retrieve the user information from the repository by the username.

@Service
public class MyUserService implements UserDetailsService {

    @Autowired
    MyUserRepository myUserRepository;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        Optional<MyUser> myUser = myUserRepository.findFirstByUsername(s);

        return myUser.map( (user) -> {
            return new MySpringUser(
                    user,
                    user.getMyAuthorities().stream().
                            map( authority ->
                                    new SimpleGrantedAuthority(authority.getName())).
                            collect(Collectors.toList()));
        }).orElseThrow(() -> new UsernameNotFoundException("user not found"));
    }
}

And now you can inject the UserDetailService because its implementation will be injected form MyUserService class.

@Autowired
private UserService userService;

@Autowired
private void configureGlobal(AuthenticationManagerBuilder auth)
        throws Exception {

    auth.userDetailsService(userService);
}

then with this approach you can inject the Principal object to your controller, and inside the method you can cast the Principal object to MySpringUser, it is because MySpringUser is extended from org.springframework.security.core.userdetails.User and User class implements the UserDetails interface. Of course you can get all the rest of custom fields of the user because its definition is wrapped inside the org.springframework.security.core.userdetails.User class

@PostMapping("/get_all_items/add_item_page/add_item")
public String addItem(@RequestParam(value = "description")
                          final String description, Principal principal) {

    MySpringUser mySpringUser = (MySpringUser)principal;

    final Item item = new Item();

    item.setDescription(description);

    item.setAuthorId(mySpringUser.getUser().getId());

    service.add(item);

    return "redirect:get_all_items";
}


Source: stackoverflow