首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Http会话是AuthenticatedWebSession Wicket和Spring安全中的空值

Http会话是AuthenticatedWebSession Wicket和Spring安全中的空值
EN

Stack Overflow用户
提问于 2017-09-04 07:58:31
回答 1查看 957关注 0票数 0

环境:

代码语言:javascript
运行
复制
<wicket.version>7.7.0</wicket.version>
<spring.version>4.3.8.RELEASE</spring.version>
<springsecurity.version>4.2.3.RELEASE</springsecurity.version>

我有来自AuthenticatedWebSession的自定义类,如:

代码语言:javascript
运行
复制
public class WicketSession extends AuthenticatedWebSession {

    private static final Logger log = LoggerFactory.getLogger(WicketSession.class);

    private static final long serialVersionUID = 1L;

    private final HttpSession httpSession;

    @SpringBean(name = "authenticationManager")
    private AuthenticationManager authenticationManager;

    public WicketSession(Request request) {
        super(request);
        this.httpSession = ((HttpServletRequest) request.getContainerRequest()).getSession();
        log.debug("Got httpSession: {}", this.httpSession);
        Injector.get().inject(this);
    }

    @Override
    public boolean authenticate(String username, String password) {
        try {
            final Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
            log.debug("Username '{}' is {} auth with authorities: {}",
                    username, auth.isAuthenticated(), auth.getAuthorities());
            if (auth.isAuthenticated()) {
                // the authentication object has to be stored in the SecurityContextHolder and in the HttpSession manually, so that the
                // security context will be accessible in the next request
                SecurityContextHolder.getContext().setAuthentication(auth);
                httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
                        SecurityContextHolder.getContext());
                return true;
            } else {
                return false;
            }
        } catch (AuthenticationException e) {
            log.warn("Failed login attempt due to exception!", e);
            return false;
        }
    }


}

类似Spring的安全控制:

代码语言:javascript
运行
复制
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    public SpringSecurityConfig() {
        super(false);
    }

    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        final InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("admin").password("admin").roles("ADMIN").build());
        manager.createUser(User.withUsername("rudi").password("rudi").roles("USER").build());
        return manager;
    }

    @Bean(name = "authenticationManager")
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/user/**").authenticated()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/**").permitAll()
                .and().formLogin().loginPage("/login")
                .and().addFilter(new SecurityContextPersistenceFilter()).securityContext();
    }    
}

弹簧应用程序类似:

代码语言:javascript
运行
复制
@PropertySource({"classpath:/META-INF/rcommerce.properties"})
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@Import({
    SpringSecurityConfig.class})
public class AppConfig {

    @Bean
    public AuthenticatedWebApplication webApp() {
        return new WicketApplication();
    }

}

来自AbstractSecurityWebApplicationInitializer的自定义类如下:

代码语言:javascript
运行
复制
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    public SecurityWebApplicationInitializer() {
        super(SpringSecurityConfig.class);
    }

}

web.xml:

代码语言:javascript
运行
复制
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <display-name>rcommerce</display-name>

    <!-- WICKET FILTER-->
    <filter>
        <filter-name>wicket.rcommerce</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
            <param-name>applicationFactoryClassName</param-name>
            <param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
        </init-param>
        <init-param>
            <param-name>applicationBean</param-name>
            <param-value>webApp</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>wicket.rcommerce</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- MDC FILTER -->
    <filter>
        <description>A servlet filter that inserts various values retrieved from the incoming http request into the MDC.</description>
        <filter-name>MDCInsertingServletFilter</filter-name>
        <filter-class>ch.qos.logback.classic.helpers.MDCInsertingServletFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MDCInsertingServletFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>MoreMdcServletFilter</filter-name>
        <filter-class>com.rudiwijaya.rcommerce.servlet.MoreMdcServletFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MoreMdcServletFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- SPRING REST SERVLET-->
    <servlet>
        <servlet-name>spring-web</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
<!--        <init-param> -->
            <!-- use just the root WebApplicationContext -->
<!--            <param-name>contextConfigLocation</param-name> -->
<!--            <param-value>org.soluvas.sanad.app.ServletConfig</param-value> -->
<!--            <param-value></param-value> -->
<!--        </init-param> -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-web</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <!-- SPRING REST FILTER-->
    <filter>
        <filter-name>httpPutFormFilter</filter-name>
        <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>httpPutFormFilter</filter-name>
        <servlet-name>spring-web</servlet-name>
    </filter-mapping>

    <!-- The SpringWebApplicationFactory will need access to a Spring Application 
        context, configured like this... -->
    <!-- SPRING CONFIG -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.rudiwijaya.rcommerce.AppConfig</param-value>
    </context-param>

    <!-- LISTENERS -->
    <listener>
        <listener-class>ch.qos.logback.classic.selector.servlet.ContextDetachingSCL</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <!-- ERROR PAGE HANDLING -->
    <error-page>
        <error-code>404</error-code>
        <location>/404.html</location>
    </error-page>

    <!-- TIMEOUT -->
    <session-config>
        <session-timeout>120</session-timeout>
    </session-config>

</web-app>

当我调用session.signIn时,得到的错误如下:

代码语言:javascript
运行
复制
Root cause:

java.lang.NullPointerException
     at com.rudiwijaya.rcommerce.WicketSession.authenticate(WicketSession.java:60)
     at org.apache.wicket.authroles.authentication.AuthenticatedWebSession.signIn(AuthenticatedWebSession.java:66)
     at com.rudiwijaya.rcommerce.pages.LoginButton.doAuthenticate(LoginButton.java:132)
     at com.rudiwijaya.rcommerce.pages.LoginButton.onSubmit(LoginButton.java:165)
     at org.apache.wicket.ajax.markup.html.form.AjaxButton$1.onSubmit(AjaxButton.java:113)
     at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior$AjaxFormSubmitter.onSubmit(AjaxFormSubmitBehavior.java:215)
     at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1307)
     at org.apache.wicket.markup.html.form.Form.process(Form.java:976)
     at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:797)
     at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.onEvent(AjaxFormSubmitBehavior.java:171)
     at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:155)
     at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:601)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at org.apache.wicket.RequestListenerInterface.internalInvoke(RequestListenerInterface.java:258)
     at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:241)
     at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.invokeListener(ListenerInterfaceRequestHandler.java:248)
     at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.respond(ListenerInterfaceRequestHandler.java:234)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:895)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)

错误(,即httpSession为null)如下:

代码语言:javascript
运行
复制
httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
                        SecurityContextHolder.getContext());

请问我该怎么办?

EN

回答 1

Stack Overflow用户

发布于 2017-09-04 21:21:26

您有多个web容器节点吗?与会话复制?

作为一般规则,您永远不应该保留对Http会话的硬引用。尤其是在Wicket应用程序中!因为如果WicketSession被序列化,然后反序列化,那么这个成员字段将是null

在需要时更好地查找HttpSession,即在方法中提取((HttpServletRequest) request.getContainerRequest()).getSession();,并在方法的主体中需要会话时调用它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46032653

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档