In some scenarios we need to get who the current user is? If you are using Spring Secrity as a security framework you can get the current user by using the following means.

SecurityContext

Either in stateful Session mode or in the popular JWT mode you can use SecurityContext to get the current user.

1
2
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();

Of course, this approach is not rigorous enough, if the interface allows anonymous access is likely to return an anonymous user, and anonymous users can not be obtained directly through getName, so we need to optimize the above logic.

1
2
3
4
5
6
7
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
    String currentUserName = authentication.getName();
    return currentUserName;
}else{
    throw RuntimeException("No User")
}

In fact, I usually use this approach the most. I like to use an abstract parent controller to encapsulate the method of getting the current user.

Principal

java.security.Principal object can also get the current user information, in Spring Security this object is represented as Authentication object, if we define Principal object in Spring MVC interface we can also get the current user.

1
2
3
4
@GetMapping("/currentusername")
public String currentUserName(Principal principal) {
        return principal.getName();
}

Similarly, the Authentication object is also possible.

1
2
3
4
 @GetMapping("/currentusername")
 public String currentUserName(Authentication authentication) {
        return authentication.getName();
 }

AuthenticationPrincipal

Many times we customize the user object UserDetails , we can get the custom UserDetails object for the current user by using the annotation @AuthenticationPrincipal provided by Spring Security 4.0. If CustomUser is an implementation of UserDetails, then we can do this.

1
2
3
4
@GetMapping("/currentusername")
 public String currentUserName(@AuthenticationPrincipal CustomUser customUser) {
   return customUser.getUsername();
}

It could be simpler.

1
2
3
4
@GetMapping("/currentusername")
 public String currentUserName(@AuthenticationPrincipal(expression = "username") String username) {
   return username;
}

This requires CustomUser to contain a getUsername method.

It is even possible to customize an annotation.

1
2
3
4
5
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {}

CurrentSecurityContext

Spring Security 5 provides a new annotation @CurrentSecurityContext to get the current user’s security context, which you can do.

1
2
3
4
5
@GetMapping("/currentusername")
public String currentUserName(@CurrentSecurityContext(expression = "authentication") 
  Authentication authentication) {
        return authentication.getName();
}

Of course you can also declare SpEL expressions with the expression parameter to get other properties, such as getting the Principal object.

1
2
3
4
5
@GetMapping("/principal")
public String getPrincipal(@CurrentSecurityContext(expression = "authentication.principal") 
  Principal principal) { 
    return principal.getName(); 
}

HttpServletRequest

The getUserPrincipal() method of HttpServletRequest is said to work, but I haven’t used it, so if you’re interested, try getting it directly from the method in the Spring Security framework.

Summary

Today we have summarized the various ways how to get the current user in Spring Security, each of them has slightly different scenarios, you can choose the most suitable scenario for your application based on these listings.

Reference https://felord.cn/securityContext.html