سؤال

وأنا جديدة نسبيا إلى الربيع والأمن الربيع.

وكنت تحاول كتابة برنامج حيث كنت بحاجة إلى مصادقة مستخدم في نهاية الخادم باستخدام الأمنية الربيع،

وخطرت لي ما يلي:

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 هو كائن من بعض الفئة التي أستطيع الوصول طوال كود خدمة بلدي عبر طلبات المستخدم متعددة.

هل كانت مفيدة؟

المحلول

وصديقك هنا هو <وأ href = "http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/context/request/RequestContextHolder.html" يختلط = "noreferrer "> 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
}

وسوف يتم ملؤها ذلك من خلال فصل الربيع القياسية MVC بريمج الإرسال، ولكن إذا كنت تستخدم إطار الشبكة مختلفة لديك إضافة org.springframework.web.filter.RequestContextFilter كمرشح في web.xml لإدارة حامل.

تعديل : في تماما كما قضية جانبية ما كنت في الواقع تحاول أن تفعل، وأنا لست متأكدا ما ينبغي عليك الوصول إلى HttpSession في طريقة retieveUser من UserDetailsService. سوف الأمنية الربيع وضعت الاعتراض على UserDetails في الدورة لك أي كيف. ويمكن استرجاعها عن طريق الوصول إلى 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;
}

نصائح أخرى

ومنذ كنت تستخدم الربيع، والعصا مع الربيع، لا الإختراق بنفسك مثل منصب يفترض الأخرى.

href="http://static.springsource.org/spring-security/site/docs/3.0.x/reference/technical-overview.html" دليل الربيع يقول:

<اقتباس فقرة>   

ويجب أن لا تتفاعل مباشرة مع HttpSession للأمن   المقاصد. وببساطة ليس هناك مبرر للقيام بذلك - استخدام دائما   وSecurityContextHolder بدلا من ذلك.

وأفضل الممارسات المقترحة للوصول إلى الدورة هي:

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

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

والمفتاح هنا هو أن الربيع والأمن الربيع تفعل كل أنواع الأشياء العظيمة بالنسبة لك مثل التثبيت منع الدورة. تفترض هذه الأشياء التي كنت تستخدم إطار الربيع كما تم تصميمه ليتم استخدامها. وهكذا، في بريمج، وجعله السياق علم والوصول إلى الدورة كما في المثال أعلاه.

إذا كنت بحاجة فقط لتخبئة بعض البيانات في نطاق الدورة، محاولة خلق بعض جلسة خاصة بتطبيق الفول مثل <وأ href = "https://stackoverflow.com/questions/10034993/spring-store-object-in-session" > هذا المثال والسماح autowire تفعل سحرها. :)

والواقع يمكنك الوصول إلى المعلومات من الدورة حتى عندما يتم تدمير الدورة على 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);

وأنا جعلت تيلس الخاصة. هو مفيد. :)

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

}

وأنا أحاول مع رمز المقبل، والعمل الممتاز

    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.x من يمكنك استخدام @AuthenticationPrincipal وعلامة @EnableWebSecurity التي تقدمها الربيع كما هو مبين أدناه.

والدرجة تكوين الأمان:

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

وطريقة تحكم:

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

في السيناريو بلدي، لقد حقنت 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);
}

و}

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
attr.getSessionId();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top