Soy relativamente nuevo en Spring y Spring Security.
Estaba intentando escribir un programa en el que necesitaba autenticar a un usuario en el extremo del servidor utilizando la seguridad de Spring,
Se me ocurrió lo siguiente:
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
}
}
Mi caso de uso es que cuando un usuario está autenticado, necesito colocar un atributo como:
session.setAttribute("userObject", myUserObject);
myUserObject es un objeto de alguna clase al que puedo acceder a través del código de mi servidor a través de múltiples solicitudes de usuario.
fuente
<listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener>
Ya que está usando Spring, quédese con Spring, no lo piratee usted mismo como las otras publicaciones.
El manual de Spring dice:
La mejor práctica sugerida para acceder a la sesión es:
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { String username = ((UserDetails)principal).getUsername(); } else { String username = principal.toString(); }
La clave aquí es que Spring y Spring Security hacen todo tipo de cosas excelentes para usted, como Prevención de fijación de sesiones. Estas cosas suponen que está utilizando el marco Spring tal como fue diseñado para su uso. Entonces, en su servlet, hágalo consciente del contexto y acceda a la sesión como en el ejemplo anterior.
Si solo necesita guardar algunos datos en el alcance de la sesión, intente crear un bean con alcance de sesión como este ejemplo y deje que autowire haga su magia. :)
fuente
hice mis propias utilidades. es útil. :)
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 应卓([email protected]) * */ 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; } } }
fuente
De hecho, puede acceder a la información de la sesión incluso cuando la sesión se está destruyendo en un HttpSessionLisener haciendo:
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 } }
o también puede acceder a la información en cualquier lugar donde tenga el objeto HttpSession disponible como:
SecurityContextImpl sci = (SecurityContextImpl) session().getAttribute("SPRING_SECURITY_CONTEXT");
el último asumiendo que tienes algo como:
HttpSession sesssion = ...; // can come from request.getSession(false);
fuente
Intento con el siguiente código y trabajo excelente
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; }
fuente
Si todo lo que necesita son los detalles del usuario, para Spring Version 4.x puede usar
@AuthenticationPrincipal
y@EnableWebSecurity
la etiqueta proporcionada por el resorte como se muestra a continuación.Clase de configuración de seguridad:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { ... }
Método de controlador:
@RequestMapping("/messages/inbox") public ModelAndView findMessagesForUser(@AuthenticationPrincipal User user) { ... }
fuente
En mi escenario, he inyectado HttpSession en la clase CustomAuthenticationProvider de esta manera
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); } }
fuente
fuente