web-dev-qa-db-fra.com

Comment obtenir l'objet utilisateur actuellement connecté à partir de Spring Security?

J'utilise la version de sécurité 3.1.4.RELEASE ..__ de Spring. Comment puis-je accéder à l'objet utilisateur actuellement connecté?

SecurityContextHolder.getContext().getAuthentication().getPrinciple()

renvoie le nom d'utilisateur, pas l'objet utilisateur. Alors, comment puis-je utiliser le nom d'utilisateur renvoyé et obtenir l'objet UserDetails?

J'ai essayé le code suivant:

public UserDetails getLoggedInUser(){

    final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null && auth.isAuthenticated() && !(auth instanceof AnonymousAuthenticationToken))
    {
        if(auth.getDetails() !=null)
            System.out.println(auth.getDetails().getClass());
        if( auth.getDetails() instanceof UserDetails)
        {
            System.out.println("UserDetails");
        }
        else
        {
            System.out.println("!UserDetails");
        }
    }
    return null;
}

Voici le résultat:

[2015-08-17 19:44:46.738] INFO  http-bio-8443-exec-423   System.out    class org.springframework.security.web.authentication.WebAuthenticationDetails 
[2015-08-17 19:44:46.738] INFO  http-bio-8443-exec-423   System.out    !UserDetails

Classe AuthenticationFilter comme suit:

public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
    public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
    private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
    private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
    private boolean postOnly = true;

    public CustomUsernamePasswordAuthenticationFilter() {
        super("/j_spring_security_check");
    }

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String username = obtainUsername(request);
        String password = obtainPassword(request);
        if (username == null) {
            username = "";
        }
        if (password == null) {
            password = "";
        }
        username = username.trim();
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);
        if(this.getAuthenticationManager()==null){
            logger.info("Authentication manager is null.");
        } else {
            logger.info("Authentication manager was "+this.getAuthenticationManager().getClass().getName()); 
        }
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(passwordParameter);
    }

    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(usernameParameter);
    }

    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    public void setUsernameParameter(String usernameParameter) {
        this.usernameParameter = usernameParameter;
    }

    public void setPasswordParameter(String passwordParameter) {
        this.passwordParameter = passwordParameter;
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getUsernameParameter() {
        return usernameParameter;
    }

    public final String getPasswordParameter() {
        return passwordParameter;
    }
}

AuthenticationProvider comme suit:

@Component
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    private MyUserDetailsService userDetailsService;

    public MyUserDetailsService getUserDetailsService() {
        return userDetailsService;
    }

    public void setUserDetailsService(MyUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails arg0,
            UsernamePasswordAuthenticationToken arg1)
            throws AuthenticationException {

    }

    @Override
    protected UserDetails retrieveUser(String arg0,
            UsernamePasswordAuthenticationToken arg1)
            throws AuthenticationException {
        return userDetailsService.loadUserByUsername(arg0);
    }
}

Classe UserDetails comme suit:

    public class MyUserDetailsService implements UserDetailsService {       
    private final Map<String, UserDetails> usersList;

    public MyUserDetailsService() {
        Collection<GrantedAuthority> authorityList;
        final SimpleGrantedAuthority supervisorAuthority = new SimpleGrantedAuthority("supervisor");
        final SimpleGrantedAuthority userAuthority = new SimpleGrantedAuthority("user");
        usersList = new TreeMap<String, UserDetails>();

        authorityList = new ArrayList<GrantedAuthority>();
        authorityList.add(supervisorAuthority);
        authorityList.add(userAuthority);
        usersList.put("admin", new User("admin", "admin", authorityList));

        authorityList = new ArrayList<GrantedAuthority>();
        authorityList.add(userAuthority);
        usersList.put("peter", new User("peter", "password123", authorityList));

        //probably don't use this in production
        for(Map.Entry<String, UserDetails> user : usersList.entrySet()){
            logger.info(user.getValue().toString());
        }
    }

    @Override
    public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
        UserDetails ud = usersList.get(username);
        if (ud != null) {
            logger.info("loadUserByUsername: found match, returning "
                    + ud.getUsername() + ":" + ud.getPassword() + ":"
                    + ud.getAuthorities().toString());
            return new User(ud.getUsername(), ud.getPassword(),
                    ud.getAuthorities());
        }

        logger.info("loadUserByUsername: did not find match, throwing UsernameNotFoundException");
        throw new UsernameNotFoundException(username);
    }
}
14
Leejoy
SecurityContextHolder.getContext().getAuthentication().getPrincipal();

Retourne l'objet utilisateur actuel. Cela peut être User, UserDetails ou votre custom user object. Vous devrez convertir l'objet de retour en UserDetails ou votre propre objet utilisateur s'il s'agit d'un objet personnalisé.

OU vous pouvez injecter Authentication ou Principal directement dans vos contrôleurs . Principle est votre UserDetails/objet utilisateur personnalisé.

Note: UserDetails est une interface

17
sura2k

vous pouvez l'utiliser comme 

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}

c'est au printemps référence de sécurité http://docs.spring.io/spring-security/site/docs/4.0.2.RELEASE/reference/htmlsingle/#obtaining-information-about-the-current-user

8
Bassem Reda Zohdy

Vous venez de faire un pas foo loin. SecurityContextHolder.getContext().getAuthentication() renvoie un objet Authentication. Vous devriez savoir comment vous avez authentifié l'utilisateur et ce que peut faire la classe concrète implémentant Authentication. En supposant qu'il s'agisse d'une sous-classe de AbstractAuthenticationToken (toutes les implémentations fournies par Spring sont), et que getDetails() renvoie une UserDetails, vous pouvez simplement utiliser:

AbstractAuthenticationToken auth = (AbstractAuthenticationToken)
    SecurityContextHolder.getContext().getAuthentication();
UserDetails details = (UserDetails) auth.getDetails();
6
Serge Ballesta

Vous pouvez simplement injecter l'interface d'authentification à votre contrôleur et obtenir le nom d'utilisateur de l'utilisateur connecté, comme ci-dessous:

@Controller
public class SomeController {

    @GetMapping(value = "/username")
    @ResponseBody
    public String currentUserName(Authentication authentication) {

        if (authentication != null) {
            return authentication.getName();

        } else {
            return "";
        }
    }
}
0
Samim