Question

Les Spring et la sécurité de Spring sont relativement nouveaux.

J'essayais d'écrire un programme nécessitant l'authentification d'un utilisateur côté serveur à l'aide de la sécurité Spring,

Je suis arrivé avec ce qui suit:

public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider{
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken)
                    throws AuthenticationException
    {
        System.out.println("Method invoked : additionalAuthenticationChecks isAuthenticated ? :"+usernamePasswordAuthenticationToken.isAuthenticated());
    }

    @Override
    protected UserDetails retrieveUser(String username,UsernamePasswordAuthenticationToken authentication) throws AuthenticationException 
    {
        System.out.println("Method invoked : retrieveUser");
        //so far so good, i can authenticate user here, and throw exception if not authenticated!!
        //THIS IS WHERE I WANT TO ACCESS SESSION OBJECT
    }
}

Mon cas d'utilisation est que lorsqu'un utilisateur est authentifié, je dois placer un attribut tel que:

session.setAttribute("userObject", myUserObject);

myUserObject est un objet d'une classe à laquelle je peux accéder via le code de mon serveur via plusieurs demandes d'utilisateurs.

Était-ce utile?

La solution

Votre ami ici est org.springframework.web.context.request.RequestContextHolder

// example usage
public static HttpSession session() {
    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    return attr.getRequest().getSession(true); // true == allow create
}

Ceci sera renseigné par le servlet standard de répartition Spring mvc, mais si vous utilisez un autre framework Web, vous devez ajouter org.springframework.web.filter.RequestContextFilter en tant que filtre dans votre web.xml pour gérer le titulaire.

MODIFIER : à titre accessoire, qu'essayez-vous réellement de faire, je ne suis pas sûr que vous ayez besoin d'un accès au HttpSession dans retieveUser méthode d'un UserDetailsService . La sécurité de printemps mettra l'objet UserDetails dans la session pour vous, peu importe comment. Vous pouvez le récupérer en accédant à SecurityContextHolder :

.
public static UserDetails currentUserDetails(){
    SecurityContext securityContext = SecurityContextHolder.getContext();
    Authentication authentication = securityContext.getAuthentication();
    if (authentication != null) {
        Object principal = authentication.getPrincipal();
        return principal instanceof UserDetails ? (UserDetails) principal : null;
    }
    return null;
}

Autres conseils

Puisque vous utilisez Spring, restez-en à Spring, ne le piratez pas comme l’autre post.

Le Manuel de printemps dit:

  

Vous ne devez pas interagir directement avec HttpSession pour des raisons de sécurité.   fins. Il n’ya simplement aucune justification à le faire - utilisez toujours   le SecurityContextHolder à la place.

La meilleure pratique suggérée pour accéder à la session est la suivante:

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

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

La clé ici est que Spring et Spring Security font toutes sortes d’excellentes choses comme la prévention de la fixation de session. Ces choses supposent que vous utilisez le framework Spring tel qu'il a été conçu pour être utilisé. Donc, dans votre servlet, indiquez le contexte et accédez à la session comme dans l'exemple ci-dessus.

Si vous avez juste besoin de cacher des données dans l'étendue de la session, essayez de créer un bean tel que cet exemple et laissez autowire faire sa magie. :)

En effet, vous pouvez accéder aux informations de la session même lorsque celle-ci est en cours de destruction sur un HttpSessionLisener en effectuant les actions suivantes:

public void sessionDestroyed(HttpSessionEvent hse) {
    SecurityContextImpl sci = (SecurityContextImpl) hse.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
    // be sure to check is not null since for users who just get into the home page but never get authenticated it will be
    if (sci != null) {
        UserDetails cud = (UserDetails) sci.getAuthentication().getPrincipal();
        // do whatever you need here with the UserDetails
    }
 }

ou vous pouvez également accéder aux informations partout où vous avez l'objet HttpSession disponible comme:

SecurityContextImpl sci = (SecurityContextImpl) session().getAttribute("SPRING_SECURITY_CONTEXT");

le dernier en supposant que vous ayez quelque chose comme:

HttpSession sesssion = ...; // can come from request.getSession(false);

J'ai fabriqué mes propres utils. c'est pratique. :)

package samples.utils;

import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.MessageSource;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.ui.context.Theme;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.support.RequestContextUtils;


/**
 * SpringMVC通用工具
 * 
 * @author 应卓(yingzhor@gmail.com)
 *
 */
public final class WebContextHolder {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebContextHolder.class);

    private static WebContextHolder INSTANCE = new WebContextHolder();

    public WebContextHolder get() {
        return INSTANCE;
    }

    private WebContextHolder() {
        super();
    }

    // --------------------------------------------------------------------------------------------------------------

    public HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        return attributes.getRequest();
    }

    public HttpSession getSession() {
        return getSession(true);
    }

    public HttpSession getSession(boolean create) {
        return getRequest().getSession(create);
    }

    public String getSessionId() {
        return getSession().getId();
    }

    public ServletContext getServletContext() {
        return getSession().getServletContext();    // servlet2.3
    }

    public Locale getLocale() {
        return RequestContextUtils.getLocale(getRequest());
    }

    public Theme getTheme() {
        return RequestContextUtils.getTheme(getRequest());
    }

    public ApplicationContext getApplicationContext() {
        return WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    }

    public ApplicationEventPublisher getApplicationEventPublisher() {
        return (ApplicationEventPublisher) getApplicationContext();
    }

    public LocaleResolver getLocaleResolver() {
        return RequestContextUtils.getLocaleResolver(getRequest());
    }

    public ThemeResolver getThemeResolver() {
        return RequestContextUtils.getThemeResolver(getRequest());
    }

    public ResourceLoader getResourceLoader() {
        return (ResourceLoader) getApplicationContext();
    }

    public ResourcePatternResolver getResourcePatternResolver() {
        return (ResourcePatternResolver) getApplicationContext();
    }

    public MessageSource getMessageSource() {
        return (MessageSource) getApplicationContext();
    }

    public ConversionService getConversionService() {
        return getBeanFromApplicationContext(ConversionService.class);
    }

    public DataSource getDataSource() {
        return getBeanFromApplicationContext(DataSource.class);
    }

    public Collection<String> getActiveProfiles() {
        return Arrays.asList(getApplicationContext().getEnvironment().getActiveProfiles());
    }

    public ClassLoader getBeanClassLoader() {
        return ClassUtils.getDefaultClassLoader();
    }

    private <T> T getBeanFromApplicationContext(Class<T> requiredType) {
        try {
            return getApplicationContext().getBean(requiredType);
        } catch (NoUniqueBeanDefinitionException e) {
            LOGGER.error(e.getMessage(), e);
            throw e;
        } catch (NoSuchBeanDefinitionException e) {
            LOGGER.warn(e.getMessage());
            return null;
        }
    }

}

J'essaie avec le code suivant et fonctionne parfaitement

    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;

    /**
     * Created by jaime on 14/01/15.
     */

    @Controller
    public class obteinUserSession {
        @RequestMapping(value = "/loginds", method = RequestMethod.GET)
        public String UserSession(ModelMap modelMap) {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            String name = auth.getName();
            modelMap.addAttribute("username", name);
            return "hellos " + name;
        }

Si vous avez uniquement besoin d'informations sur l'utilisateur, vous pouvez utiliser les balises @AuthenticationPrincipal et @EnableWebSecurity pour Spring Version 4.x . au printemps, comme indiqué ci-dessous.

Classe de configuration de sécurité:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
   ...
}

Méthode du contrôleur:

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal User user) {
    ...
}

Dans mon scénario, j'ai injecté HttpSession dans la classe CustomAuthenticationProvider. comme ça

public class CustomAuthenticationProvider extends  AbstractUserDetailsAuthenticationProvider{

@Autowired 
private HttpSession httpSession;

@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken)
         throws AuthenticationException
{
    System.out.println("Method invoked : additionalAuthenticationChecks isAuthenticated ? :"+usernamePasswordAuthenticationToken.isAuthenticated());
}

@Override
protected UserDetails retrieveUser(String username,UsernamePasswordAuthenticationToken authentication) throws AuthenticationException 
{
    System.out.println("Method invoked : retrieveUser");
    //so far so good, i can authenticate user here, and throw exception if not authenticated!!
    //THIS IS WHERE I WANT TO ACCESS SESSION OBJECT
    httpSession.setAttribute("userObject", myUserObject);
}

}

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
attr.getSessionId();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top