मैं वसंत में सत्र वस्तु कैसे प्राप्त करूं?


88

मैं वसंत और वसंत सुरक्षा के लिए अपेक्षाकृत नया हूं ।

मैं एक प्रोग्राम लिखने की कोशिश कर रहा था जहाँ मुझे स्प्रिंग एंड सिक्योरिटी का उपयोग करके सर्वर के अंत में एक उपयोगकर्ता को प्रमाणित करने की आवश्यकता थी,

मैं निम्नलिखित के साथ आया:

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

मेरा उपयोग यह है कि जब कोई उपयोगकर्ता प्रमाणित होता है, तो मुझे एक विशेषता रखने की आवश्यकता होती है:

session.setAttribute("userObject", myUserObject);

myUserObject कुछ वर्ग का एक उद्देश्य है जिसे मैं अपने सर्वर कोड में कई उपयोगकर्ता अनुरोधों तक पहुंचा सकता हूं।

जवाबों:


146

आपका दोस्त यहाँ है 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
}

यह मानक स्प्रिंग एमवीसी प्रेषण सर्वलेट द्वारा पॉप्युलेट किया जाएगा, लेकिन यदि आप धारक को प्रबंधित करने के लिए एक अलग वेब फ्रेमवर्क का उपयोग कर रहे हैं जिसे आपने org.springframework.web.filter.RequestContextFilterफ़िल्टर के रूप में जोड़ा है web.xml

संपादित करें : एक पक्ष के मुद्दे के रूप में आप वास्तव में क्या करने की कोशिश कर रहे हैं, मुझे यकीन नहीं है कि आपको ए HttpSessionकी retieveUserविधि में पहुंच की आवश्यकता होनी चाहिए UserDetailsService। स्प्रिंग सिक्योरिटी आपके लिए किसी भी तरह से सत्र में यूजरडेल्स ऑब्जेक्ट डाल देगी। इसे एक्सेस करके प्राप्त किया जा सकता है 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
@ फ़र्स्ट पॉइंट: मैंने RequestContextHolder का उपयोग करने की कोशिश की, इसने मुझे एक त्रुटि दी: कोई थ्रेड-बाउंड अनुरोध नहीं मिला: क्या आप इसका उल्लेख कर रहे हैं ... वर्तमान अनुरोध को उजागर करने के लिए RequestContextListener या RequestContextFilter का उपयोग करें। मुझे लगता है मैं कोशिश करता हूँ फिल्टर नहीं है, कोशिश करेंगे कि चलो और पता है अगर यह काम करता है। @ सेकेंड पॉइंट: वास्तव में इसका एक कस्टम ऑब्जेक्ट है, इसलिए यदि संभव हो तो मैं UserDetails पसंद नहीं करता यदि संभव हो तो इसी तरह के विषय पर मेरे अन्य प्रश्न देखें: stackoverflow.com/questions/1629273/…
Salvin Francis

2
यदि आप डिस्पैच सर्वलेट का उपयोग नहीं कर रहे हैं तो आपको कॉन्फ़िगर करने की आवश्यकता है: RequestContextFilter
Gareth Davis

1
क्षमा करें मेरी गलती ... मेरे अपने प्रोजेक्ट से कोड को अनुकूलित किया जो getRequest का उपयोग करता है, उत्तर अपडेट किया गया है
गैरेथ डेविस

1
नहीं है कि सही के बारे में लग रहा है ... एक डिबगर में अपने कोड को रोकने की कोशिश करें और जाँच करें कि RequestContextFilter कॉल स्टैक में है
गैरेथ डेविस

1
मैंने पाया कि RequestContextFilter ने मेरे लिए काम नहीं किया, जबकि RequestContextListener ने ...<listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener>
जोश

33

जब से आप स्प्रिंग का उपयोग कर रहे हैं, स्प्रिंग के साथ रहना, अन्य पोस्ट पोज़िट्स की तरह इसे स्वयं हैक न करें

स्प्रिंग मैनुअल का कहना है:

आपको सुरक्षा उद्देश्यों के लिए सीधे HttpSession के साथ बातचीत नहीं करनी चाहिए। ऐसा करने का कोई औचित्य नहीं है - इसके बजाय हमेशा SecurityContextHolder का उपयोग करें।

सत्र तक पहुँचने के लिए सबसे अच्छा सुझाव है:

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

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

यहाँ कुंजी यह है कि स्प्रिंग और स्प्रिंग सिक्योरिटी आपके लिए सेशन फिक्सेशन प्रिवेंशन जैसे सभी तरह के बेहतरीन सामान उपलब्ध कराती है। ये चीजें मानती हैं कि आप स्प्रिंग फ्रेमवर्क का उपयोग कर रहे हैं क्योंकि इसका उपयोग करने के लिए डिज़ाइन किया गया था। इसलिए, अपने सर्वलेट में, इसे संदर्भ में अवगत कराएं और उपरोक्त उदाहरण की तरह सत्र का उपयोग करें।

यदि आपको सत्र के दायरे में कुछ डेटा को स्टैश करना है, तो इस उदाहरण की तरह कुछ सत्र स्कॉप्ड बीन बनाने का प्रयास करें और ऑटोवेयर को अपना जादू करने दें। :)


5

मैंने अपने बर्तन खुद बनाए। यह आसान है। :)

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

वास्तव में आप सत्र से जानकारी तब भी प्राप्त कर सकते हैं जब सत्र HttpSessionLisener पर नष्ट हो रहा हो:

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

या आप HttpSession वस्तु की तरह कहीं भी जानकारी का उपयोग कर सकते हैं:

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

अंतिम मान लेने से आपके पास कुछ ऐसा है:

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

3

मैं अगले कोड के साथ कोशिश करता हूं और उत्कृष्ट काम करता हूं

    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
कृपया अपने कोड के साथ एक स्पष्टीकरण जोड़ें। इधर-उधर बस किसी सवाल पर कोड या लिंक फेंकना वास्तव में एक जवाब नहीं है।
रेमी

1

यदि आपके लिए आवश्यक सभी का विवरण स्प्रिंग संस्करण 4.x के लिए है, तो आप नीचे दिए गए अनुसार स्प्रिंग द्वारा प्रदान किए गए टैग @AuthenticationPrincipalऔर @EnableWebSecurityटैग का उपयोग कर सकते हैं ।

सुरक्षा कॉन्फ़िगरेशन क्लास:

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

नियंत्रक विधि:

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

1

मेरे परिदृश्य में, मैंने HttpSession को इस तरह के CustomAuthenticationProvider वर्ग में इंजेक्ट किया है

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
क्या आप कृपया अपने उत्तर में कुछ अतिरिक्त जानकारी जोड़ सकते हैं कि यह अन्य मौजूदा उत्तरों की तुलना में समस्या को कैसे हल करता है?
स्लफान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.