Je suis relativement nouveau à Spring et à Spring Security.
J'essayais d'écrire un programme où je devais authentifier un utilisateur côté serveur en utilisant la sécurité Spring,
Je suis venu 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 requêtes utilisateur.
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
}
Ce dernier sera renseigné par le servlet standard de dispatch mvc de Spring, mais si vous utilisez un autre framework Web, vous devez ajouter org.springframework.web.filter.RequestContextFilter
comme filtre dans votre web.xml
pour gérer le titulaire.
[~ # ~] modifier [~ # ~] : juste une question secondaire: qu'essayez-vous réellement de faire, je ne suis pas sûr que vous devriez le faire besoin d'accéder à la HttpSession
dans la méthode retieveUser
d'un UserDetailsService
. La sécurité de printemps mettra l'objet UserDetails dans la session pour vous, peu importe comment. Il peut être récupéré en accédant à la 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;
}
Puisque vous utilisez Spring, restez avec Spring, ne le piratez pas vous-même comme le dit le post précédent.
Le manuel de printemps dit:
Vous ne devez pas interagir directement avec HttpSession à des fins de sécurité. Il n'y a tout 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 au contexte et accédez à la session comme dans l'exemple ci-dessus.
Si vous avez juste besoin de stocker certaines données dans l'étendue de la session, essayez de créer un bean de la portée de la session tel que cet exemple et laissez autowire faire son travail de magie. :)
j'ai fait 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 应卓([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;
}
}
}
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 procédant comme suit:
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'essaie avec le code suivant et travaille excellent
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 tout ce dont vous avez besoin est des détails sur l'utilisateur, pour Spring Version 4.x vous pouvez utiliser @AuthenticationPrincipal
et @EnableWebSecurity
balise fournie par Spring 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 ceci
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();