Spring security AuthenticatedWebSession Wicket和Spring Security中的Http会话为空

Spring security AuthenticatedWebSession Wicket和Spring Security中的Http会话为空,spring-security,wicket,Spring Security,Wicket,环境: <wicket.version>7.7.0</wicket.version> <spring.version>4.3.8.RELEASE</spring.version> <springsecurity.version>4.2.3.RELEASE</springsecurity.version> Spring安全配置类似于: @Configuration @EnableWebSecurity public clas

环境:

<wicket.version>7.7.0</wicket.version>
<spring.version>4.3.8.RELEASE</spring.version>
<springsecurity.version>4.2.3.RELEASE</springsecurity.version>
Spring安全配置类似于:

@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();
    }    
}
@PropertySource({"classpath:/META-INF/rcommerce.properties"})
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@Import({
    SpringSecurityConfig.class})
public class AppConfig {

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

}
Spring应用程序配置类似于:

@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();
    }    
}
@PropertySource({"classpath:/META-INF/rcommerce.properties"})
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@Import({
    SpringSecurityConfig.class})
public class AppConfig {

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

}
来自
AbstractSecurityWebApplicationInitializer的自定义类,如:

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


}
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

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

}
web.xml:

<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>
第行中的错误(为httpSession为null):


我该怎么办?

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

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


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

httpSession
为空会话可能已过期。类从AuthenticatedApplication中派生,方法
newSession()
getWebSessionClass()
-您能在这里包括吗?谢谢@martin-g,我将尝试您的建议。在一个tomcat中没有会话复制,只有两次战争……如果我读入,MyAuthenticatedWebSession中没有httpSession,可以吗?因为在另一个示例(如或)中,存在httpSession。我删除了httpSession和行:
httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,SecurityContextHolder.getContext()),作为概念Spring Security&Wicket可以吗?IMO不需要这样做。您始终可以使用
SecurityContextHolder.getContext()
查找上下文。我的应用程序中没有它。