7

我在尝试让我的 SessionDestroyedEvent 工作时遇到问题。我希望它在会话超时时打印出来。我正在清除我的历史记录以强制它超时。

这是我的代码:

@Service
public class MyTimeoutFilter implements
        ApplicationListener<ApplicationEvent>
{
    public MyTimeoutFilter()
    {
        super();
        System.out.println("Application context listener is created!");
    }

    public void onApplicationEvent(ApplicationEvent event)
    {
        if (event instanceof SessionDestroyedEvent)
        {
            SessionDestroyedEvent sdEvent = (SessionDestroyedEvent) event;

            List<SecurityContext> lstSecurityContext = sdEvent
                    .getSecurityContexts();

            for (SecurityContext securityContext : lstSecurityContext)
            {
                System.out.println("Security Context: "
                    securityContext.getAuthentication().getName());
            }
        }

        System.out.println("This is a test.");
    }
}

我得到的只是“创建了应用程序上下文侦听器。”,然后是“这是一个测试”。我从来没有运行 if 语句中的代码。

这是我的 web.xml:

<!-- The definition of the Root Spring Container shared by all Servlets 
    and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml,
        /WEB-INF/spring/appServlet/security-context.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
    <session-timeout>1</session-timeout>
</session-config>

我没有名为“application-context.xml”的文件。然而,我确实有一个“servlet-context.xml”和一个“security-context.xml”。这是两者:

Servlet-context.xml

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<annotation-driven />

<resources mapping="/static/**" location="/static/" />

<beans:bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>

<context:component-scan base-package="com.blahblahblah.bagbox" />
<context:property-placeholder location="classpath*:jdbc.properties" />
<mvc:annotation-driven />
<tx:annotation-driven />
<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <beans:property name="order">
        <beans:value>1</beans:value>
    </beans:property>
</beans:bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<beans:bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close" p:driverClass="${app.jdbc.driverClassName}"
    p:jdbcUrl="${app.jdbc.url}" p:user="${app.jdbc.username}" p:password="${app.jdbc.password}"
    p:acquireIncrement="5" p:idleConnectionTestPeriod="60" p:maxPoolSize="100"
    p:maxStatements="50" p:minPoolSize="10" />

<beans:bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
    p:dataSource-ref="dataSource" />

</beans:beans>

这是我的 Security-context.xml

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<security:http auto-config="false" use-expressions="true"
    entry-point-ref="loginUrlAuthenticationEntryPoint">
    <security:intercept-url pattern="/login*"
        access="isAnonymous()" />
    <security:intercept-url pattern="/logout*"
        access="isAnonymous()" />
    <security:intercept-url pattern="/static/**"
        access="permitAll" />
    <security:intercept-url pattern="/**"
        access="isFullyAuthenticated()" />
    <security:intercept-url pattern="/"
        access="isFullyAuthenticated()" />
    <security:anonymous />
    <security:custom-filter ref="loginFilter"
        position="FORM_LOGIN_FILTER" />
    <security:custom-filter position="LOGOUT_FILTER"
        ref="logoutFilter" />
</security:http>

<beans:bean id="loginUrlAuthenticationEntryPoint"
    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <beans:property name="loginFormUrl" value="/login.html" />
</beans:bean>

<beans:bean id="loginFilter"
    class="com.blahblahblah.bagbox.security.filter.MyLoginFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="authenticationFailureHandler"
        ref="failureHandler" />
    <beans:property name="authenticationSuccessHandler"
        ref="successHandler" />
</beans:bean>

<beans:bean id="successHandler"
    class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    <beans:property name="defaultTargetUrl" value="/" />
</beans:bean>
<beans:bean id="failureHandler"
    class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <beans:property name="defaultFailureUrl" value="/loginFailed.html" />
</beans:bean>

<beans:bean id="logoutFilter"
    class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <beans:constructor-arg index="0" value="/login.html" />
    <beans:constructor-arg index="1">
        <beans:list>
            <beans:bean id="securityContextLogoutHandler"
                class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
            <beans:bean id="logoutHandler"
                class="com.blahblahblah.bagbox.security.filter.MyLogoutHandler" />
        </beans:list>
    </beans:constructor-arg>
    <beans:property name="filterProcessesUrl" value="/logout.html" />
</beans:bean>

<security:global-method-security
    secured-annotations="enabled" />

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider
        ref="ldapAuthProvider" />
</security:authentication-manager>

<beans:bean id="ldapAuthProvider"
    class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <beans:constructor-arg>
        <beans:ref local="bindAuthenticator" />
    </beans:constructor-arg>
    <beans:constructor-arg>
        <beans:ref local="authoritiesPopulator" />
    </beans:constructor-arg>
    <beans:property name="userDetailsContextMapper" ref="userDetailsContextMapper" />
</beans:bean>

<beans:bean id="bindAuthenticator"
    class="org.springframework.security.ldap.authentication.BindAuthenticator">
    <beans:constructor-arg ref="initialDirContextFactory" />
    <beans:property name="userSearch" ref="userSearch" />
</beans:bean>

<beans:bean id="authoritiesPopulator"
    class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <beans:constructor-arg ref="initialDirContextFactory" />
    <beans:constructor-arg value="" />
    <beans:property name="groupRoleAttribute" value="cn" />
    <beans:property name="searchSubtree" value="true" />
    <beans:property name="rolePrefix" value="ROLE_" />
    <beans:property name="convertToUpperCase" value="true" />
</beans:bean>

<beans:bean id="userDetailsContextMapper"
    class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" />

<beans:bean id="userSearch"
    class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <beans:constructor-arg index="0" value="" />
    <beans:constructor-arg index="1"
        value="(sAMAccountName={0})" />
    <beans:constructor-arg index="2"
        ref="initialDirContextFactory" />
    <beans:property name="searchSubtree" value="true" />
</beans:bean>

<beans:bean id="initialDirContextFactory"
    class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <beans:constructor-arg
        value="ldap://ccpdc.countrycurtains.local:389/dc=countrycurtains,dc=local" />
    <beans:property name="userDn"
        value="CN=LDAP BIND,CN=Users,DC=countrycurtains,DC=local" />
    <beans:property name="password" value="ld4pb1nd" />
    <beans:property name="baseEnvironmentProperties">
        <beans:map>
            <beans:entry key="java.naming.referral">
                <beans:value>follow</beans:value>
            </beans:entry>
        </beans:map>
    </beans:property>
</beans:bean>

<beans:bean id="loggerListener"
    class="org.springframework.security.authentication.event.LoggerListener" />

</beans:beans>

有很多 SessionDestroyedEvent 经验和/或获得会话超时以使用 Spring Security 的人可以帮助我。我在 Google 上查找的所有代码都指向不再有效的方法(例如 getSecurityContext(),当它已更改为 getSecurityContexts() 时)。

4

2 回答 2

3

不要忘记HttpSessionEventPublisher声明web.xml

<listener>
    <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
    </listener-class>
</listener>

另外,我不太明白清除历史记录应该如何强制会话超时。如果你想测试会话超时功能,你需要配置一些小的会话超时web.xml(例如,1 分钟),登录并等待它超时。

于 2012-11-07T15:43:45.727 回答
3

链接可能会解决您的问题。

HttpSessionEventPublisher 和您的服务类都必须在“Spring Root WebApplicationContex”下。

于 2012-11-07T17:40:45.250 回答