有时我们需要获取当前登录的用户信息(比如用户名),通常有如下几种方式来实现。
方法1:通过 Authentication.getPrincipal() 获取用户信息
(1)通过 Authentication.getPrincipal() 可以获取到代表当前用户的信息,这个对象通常是 UserDetails 的实例。通过 UserDetails 的实例我们可以获取到当前用户的用户名、密码、角色等信息。
Spring Security 使用一个 Authentication 对象来描述当前用户的相关信息,而 SecurityContext 持有的是代表当前用户相关信息的 Authentication 的引用。
这个 Authentication 对象不需要我们自己去创建,在与系统交互的过程中,Spring Security 会自动为我们创建相应的 Authentication 对象,然后赋值给当前的 SecurityContext。
1@RestController 2public class HelloController { 3 4 @GetMapping("/hello") 5 public String hello() { 6 Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 7 8 if (principal instanceof UserDetails) { 9 return ((UserDetails) principal).get.getUsername(); 10 } 11 12 if (principal instanceof Principal) { 13 return ((Principal) principal).getName(); 14 } 15 16 return "当前登录用户:" + String.valueOf(principal); 17 } 18}

(2)由于获取当前用户的用户名是一种比较常见的需求,其实 Spring Security 在 Authentication 中的实现类中已经为我们做了相关实现,所以获取当前用户的用户名有如下更简单的方式:
1@RestController 2public class HelloController { 3 4 @GetMapping("/hello") 5 public String hello() { 6 return "当前登录用户:" + SecurityContextHolder.getContext().getAuthentication().getName(); 7 } 8}
方法2:通过注入 Principal 接口获取用户信息
在运行过程中,Spring 会将 Username、Password、Authentication、Token 注入到 Principal 接口中,我们可以直接获取使用:
1@RestController 2public class HelloController { 3 4 @GetMapping("/hello") 5 public String hello(Principal principal) { 6 // 注意:如果未登录,principal 为 null 7 return "当前登录用户:" + principal.getName(); 8 } 9}
附:获取登录用户的 id 等其他信息
(1)如果我们是基于数据库的用户角色配置的话,那么会创建用户表对应的实体类,同时用户实体类需要实现 UserDetails 接口。
关于基于数据库的用户角色配置认证更详细的用法,可以参考我之前显得文章:
1@NoArgsConstructor 2@ToString 3public class User implements UserDetails { 4 private Integer id; 5 private String username; 6 private String password; 7 private Boolean enabled; 8 private Boolean locked; 9 private List<Role> roles; 10 11 @Override 12 public Collection<? extends GrantedAuthority> getAuthorities() { 13 List<SimpleGrantedAuthority> authorities = new ArrayList<>(); 14 for (Role role : roles) { 15 authorities.add(new SimpleGrantedAuthority(role.getName())); 16 } 17 return authorities; 18 } 19 20 @Override 21 public String getPassword() { 22 return password; 23 } 24 25 @Override 26 public String getUsername() { 27 return username; 28 } 29 30 @Override 31 public boolean isAccountNonExpired() { 32 return true; 33 } 34 35 @Override 36 public boolean isAccountNonLocked() { 37 return !locked; 38 } 39 40 @Override 41 public boolean isCredentialsNonExpired() { 42 return true; 43 } 44 45 @Override 46 public boolean isEnabled() { 47 return enabled; 48 } 49 50 /** get、set 方法 **/ 51 52 public Integer getId() { 53 return id; 54 } 55 56 public void setId(Integer id) { 57 this.id = id; 58 } 59 60 public void setUsername(String username) { 61 this.username = username; 62 } 63 64 public void setPassword(String password) { 65 this.password = password; 66 } 67 68 public void setEnabled(Boolean enabled) { 69 this.enabled = enabled; 70 } 71 72 public Boolean getLocked() { 73 return locked; 74 } 75 76 public void setLocked(Boolean locked) { 77 this.locked = locked; 78 } 79 80 public List<Role> getRoles() { 81 return roles; 82 } 83 84 public void setRoles(List<Role> roles) { 85 this.roles = roles; 86 } 87}
(2)我们同样通过 Authentication.getPrincipal() 可以获取当前登录用户的 UserDetails 实例,然后再转换成自定义的用户实体类 User,这样便能获取用户的 ID 等信息:
1@RestController 2public class HelloController { 3 4 @GetMapping("/hello") 5 public String hello() { 6 Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 7 User user = (User)principal; 8 return "当前登录用户信息:" + user.toString(); 9 } 10}
(3)运行结果如下:
