İlkbaharda Oturum Nesnesini nasıl edinirim?


88

Bahar ve Bahar güvenliğinde nispeten yeniyim.

Spring güvenliğini kullanarak sunucu ucunda bir kullanıcının kimliğini doğrulamak için gereken bir program yazmaya çalışıyordum,

Aşağıdakileri buldum:

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
    }
}

Benim kullanım amacım, bir kullanıcının kimliği doğrulandığında, aşağıdaki gibi bir özellik yerleştirmem gerektiğidir:

session.setAttribute("userObject", myUserObject);

myUserObject, birden çok kullanıcı isteğinde sunucu kodum boyunca erişebileceğim bazı sınıfların bir nesnesidir.

Yanıtlar:


147

Arkadaşın burada 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
}

Bu, standart yaylı mvc gönderme sunucu uygulaması tarafından doldurulur, ancak farklı bir web çerçevesi kullanıyorsanız , tutucuyu yönetmek için org.springframework.web.filter.RequestContextFilterfiltrenize bir filtre olarak eklemeniz gerekir web.xml.

DÜZENLEME : sadece bir yan sorun olarak, aslında ne yapmaya çalışıyorsunuz, HttpSessionin retieveUseryöntemine erişmeniz gerektiğinden emin değilim UserDetailsService. Bahar güvenliği, UserDetails nesnesini sizin için nasıl olursa olsun oturuma koyacaktır. Aşağıdakilere erişilerek alınabilir 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;
}

1
@birinci nokta: RequestContextHolder'ı kullanmayı denedim, bana bir hata verdi: İş parçacığına bağlı istek bulunamadı: Şu anki isteği açığa çıkarmak için ... RequestContextListener veya RequestContextFilter'a başvuruyor musunuz? Sanırım filtreleri denemedim, bunu deneyeceğim ve işe yarayıp yaramadığını size bildireceğim. @saniye noktası: aslında bu özel bir nesne, bu yüzden mümkünse UserDetails'i tercih etmedim, benzer bir konudaki diğer sorumu görüyorum: stackoverflow.com/questions/1629273/…
Salvin Francis

2
dağıtım sunucusunu kullanmıyorsanız, yapılandırmanız gerekir: RequestContextFilter
Gareth Davis

1
hatam için özür dilerim ... kodu getRequest kullanan kendi projemden uyarladım, cevap güncellendi
Gareth Davis

1
hayır, bu doğru görünüyor ... kodunuzu bir hata ayıklayıcıda durdurmayı ve RequestContextFilter'ın çağrı yığınında olduğunu kontrol etmeyi deneyin
Gareth Davis

1
RequestContextFilter'ın benim için çalışmadığını, ancak RequestContextListener'ın işe yaradığını buldum ...<listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener>
Josh

33

Spring'i kullandığınız için, Spring'e sadık kalın, diğer gönderi pozları gibi kendiniz hacklemeyin.

Bahar kılavuzu diyor ki:

Güvenlik amacıyla HttpSession ile doğrudan etkileşime girmemelisiniz. Bunu yapmak için hiçbir gerekçe yoktur - bunun yerine her zaman SecurityContextHolder'ı kullanın.

Oturuma erişmek için önerilen en iyi uygulama şudur:

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

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

Buradaki anahtar, Spring ve Spring Security'nin sizin için Oturum Sabitlemeyi Önleme gibi her türlü harika şeyi yapmasıdır. Bu şeyler, kullanılmak üzere tasarlandığı şekliyle Spring çerçevesini kullandığınızı varsayar. Bu nedenle, sunucu uygulamanızda, onu içeriğe duyarlı hale getirin ve yukarıdaki örnekte olduğu gibi oturuma erişin.

Yalnızca oturum kapsamında bazı verileri saklamanız gerekiyorsa, bu örnek gibi oturum kapsamlı bir fasulye oluşturmayı deneyin ve otomatik telin sihrini yapmasına izin verin. :)


5

kendi eşyaları yaptım. kullanışlıdır. :)

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;
        }
    }

}

4

Aslında, oturum bir HttpSessionLisener üzerinde yok edilirken bile, aşağıdakileri yaparak oturumdaki bilgilere erişebilirsiniz:

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
    }
 }

ya da HttpSession nesnesine sahip olduğunuz her yerde aşağıdaki gibi bilgilere erişebilirsiniz:

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

son olarak şuna benzer bir şeye sahip olduğunuzu varsayarsak:

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

3

Bir sonraki kodu deniyorum ve mükemmel çalışıyorum

    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;
        }

4
Lütfen kodunuzla bir açıklama ekleyin. Buralarda birine bir soruya kod veya bağlantı atmak aslında bir cevap değil.
Rémi

2

İhtiyacınız olan tek şey Kullanıcı detayları ise, Spring Sürüm 4.x için aşağıda gösterildiği gibi Spring tarafından sağlanan kullanabilir @AuthenticationPrincipalve @EnableWebSecurityetiketleyebilirsiniz.

Güvenlik Yapılandırma Sınıfı:

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

Denetleyici yöntemi:

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

1

Senaryomda, HttpSession'ı CustomAuthenticationProvider sınıfına şu şekilde enjekte ettim

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);
    }
}

0
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
attr.getSessionId();

5
Diğer mevcut cevaplara kıyasla sorunun sorunu nasıl çözdüğüne dair cevabınıza biraz ek bilgi ekleyebilir misiniz?
slfan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.