ChatGPT解决这个技术问题 Extra ChatGPT

How to find out the currently logged-in user in Spring Boot?

In this Spring Boot application there is a web service, which returns some data for a logged-in user:

@RequestMapping("/resource")
public Map<String, Object> home() {
    Map<String, Object> model = new HashMap<String, Object>();
    model.put("id", UUID.randomUUID().toString());
    model.put("content", "Hello World");
    return model;
}

Imagine, the return value of the method depends on what user is currently logged in.

How can I find out, which user is logged in in that method?


P
Peter Kovac

As per request:

Spring Boot which uses Spring Security internally provides a SecurityContextHolder class which allows the lookup of the currently authenticated user via:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

The authentication instance now provides the following methods:

Get the username of the logged in user: getPrincipal()

Get the password of the authenticated user: getCredentials()

Get the assigned roles of the authenticated user: getAuthorities()

Get further details of the authenticated user: getDetails()


Or easier and less intrusive, simply add a method argument of type Principal if you are only interested in the user, or Authentication if you want more. Saves you the hassle of working with the SecurityContextHolder.
hello how can i use where should i put this to get the logged user thank you
@KamelMili As Spring Security usually is a filter hanging right before the actual application logic is entered, you should be able to access the authentication from almost anywhere in your application. Not sure though if this answers your question
Classy (y) Answer
Get the username of the logged in user: getPrincipal() => getName() ?
N
NikolaB

Since Spring Security 3.2 you can get currently logged in user (your implementation of UserDetails) by adding a parameter inside your controller method:

import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;

@RequestMapping("/resource")
public Map<String, Object> home(@AuthenticationPrincipal User user) {
   ..
}

Replace User with the name of your class which implements UserDetails interface.

Edit:

Since Spring Security 4.0 annotation was moved to a different package:

import org.springframework.security.core.annotation.AuthenticationPrincipal;

Addendum:

This will work even in WebFlux reactive environment versus the SecurityContextHolder.getContext().getAuthentication() which won't work because of paradigm shift from thread per request model to multiple requests per thread.


This always returns null, even when Authentication auth = SecurityContextHolder.getContext().getAuthentication(); returns a user
@DanielMethner That shouldn't happen I'm using this in controllers in Webflux and Non-Webflux environments and it works everywhere. Can you open a new question and post your configuration, spring versions, and controller where it doesn't work and I'll take a look?
I forgot to send the authentication header. Problem is therefore solved. thanks anyways!
When I use @AuthenticationPrincipal UserDetailsImpl user is not null and working. This is for people using a separate class for principal other than User
N
NikhilP

You can simply use HttpServletRequest also to get user principle,

using HttpServletRequest request,

String user=request.getUserPrincipal().getName();

Y
Youcef Laidani

One way is to add java.security.Principal as a parameter as follows:

@RequestMapping("/resource")
public Map<String, Object> home(Principal principal) {
    Map<String, Object> model = new HashMap<String, Object>();
    model.put("id", UUID.randomUUID().toString());
    model.put("content", "Hello " + principal.getName());
    return model;
}

t
ttulka

Since version 5.2 you can use CurrentSecurityContext annotation:

@GetMapping("/hello")
public String hello(@CurrentSecurityContext(expression="authentication?.name")
                    String username) {
    return "Hello, " + username + "!";
}

authentication?.name to avoid null pointer when authentication is not present
@JustinasJakavonis Good point! I edit the answer. Thanks
G
Gourav

In Spring boot v2.1.9.RELEASE if you are trying to get the name, email , given_name you can get those details from Pricipal. Note: I am using spring security with google oauth2

Map<String , Object> userDetails = ((DefaultOidcUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getAttributes(); System.out.println(userDetails.get("name")); System.out.println(userDetails.get("email")); System.out.println(userDetails.get("given_name"));


P
Petko Mirchev

Recently using Keycloak authentication server and accessing currently logged-in user data is accessible like this

String userID;

KeycloakPrincipal kcPrincipal = getPrincipal();
KeycloakSecurityContext ksContext = kcPrincipal.getKeycloakSecurityContext();
IDToken idToken = ksContext.getToken();
userID = idToken.getName();

P
Petko Mirchev

Im using spring boot 2.0 with OAuth so I'm doing it like this

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Object pricipal = auth.getPrincipal();
String user="";
if (pricipal instanceof DefaultOidcUser) {
       user = ((DefaultOidcUser) pricipal).getName();
}

How I can get getName and getAttribute in JSP?
D
Deepak Sharma

You can find the currently logged in user name without using any spring Security features. All you need is a jdk 1.8

Do the following :

@RequestMapping("/login")
@Override
public ModelAndView AuthChecker(@RequestParam("email") String email, @RequestParam("password") String password, Customers cust) {

     ModelAndView mv = new ModelAndView("index");
     if((repo.findByEmail(email)!=null) && (repo.findByPassword(password)!=null)) {
        
         
      List<Customers> l=  repo.findAll();
      
      cust = (Customers) l.stream() 
      .filter(x -> email.equals(x.getEmail()))        
      .findAny()                                      
      .orElse(null); 
    
        mv.addObject("user",cust.getName());
         mv.setViewName("DashBoardRedirect");
    
         return mv;

Once name fetched successfully, you can use the same in any jsp/thymeleaf view.