かなり奇妙な問題があります。ajax 認証を使用する 1 ページの ajax アプリケーション (gmail のようなものと考えてください) があります。通常の状況では、うまく機能します。ただし、サーバーへの他のリクエストがまだ開いて実行されている間にログインしようとしていることがわかりました。ログイン試行は成功しますが、サーバーを再度呼び出してユーザー関連の何かを取得すると、オブジェクトがセッションから出てくる認証は null になります。
私が言ったように、ログイン試行の前に接続が開いていて実行されている場合は常に発生します。ログインがその時間に発生する唯一の要求である場合、すべてが期待どおりに機能します。
ここに spring-security.xml があります
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd" default-lazy-init="true">
<context:component-scan base-package="com.myProject"/> <!-- need this? -->
<security:global-method-security secured-annotations="enabled" />
<security:http pattern="/css/**" security="none" />
<security:http pattern="/js/**" security="none" />
<security:http pattern="/tmpl/**" security="none" />
<security:http pattern="/**" use-expressions="true" entry-point-ref="authenticationEntryPoint">
<security:custom-filter before="FORM_LOGIN_FILTER" ref="legacyAuthenticationProcessingFilter" />
<security:custom-filter position="FORM_LOGIN_FILTER" ref="authenticationProcessingFilter"/>
<security:logout logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<security:custom-filter before="LOGOUT_FILTER" ref="legacyLogoutFilter" />
<security:remember-me services-ref="#{applicationProperties['security.rememberMeServices']}" />
</security:http>
<security:authentication-manager alias="authenticationManager" erase-credentials="false">
<security:authentication-provider ref="activeDirectoryAuthenticationProvider" />
<security:authentication-provider ref="singleLogonAuthenticationProvider" />
<security:authentication-provider ref="serviceAuthenticationProvider" />
<security:authentication-provider ref="rememberMeAuthenticationProvider" />
</security:authentication-manager>
<!-- single logon remember me -->
<bean id="singleLogonRememberMeServices" class="com.myProject.security.singlelogon.SingleLogonRememberMeServices" c:userDetailsService-ref="userDao" c:key="#{applicationProperties['security.rememberMeServices.key']}" p:parameter="rememberMe" />
<!-- 'regular' remember me -->
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices" c:userDetailsService-ref="userDao" c:key="#{applicationProperties['security.rememberMeServices.key']}" p:parameter="rememberMe" />
<bean id="activeDirectoryAuthenticationProvider" class="com.myProject.security.activedirectory.ActiveDirectoryAuthenticationProvider" />
<bean id="singleLogonAuthenticationProvider" class="com.myProject.security.singlelogon.SingleLogonAuthenticationProvider" />
<bean id="serviceAuthenticationProvider" class="com.myProject.security.ServiceAuthenticationProvider" />
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider" p:key="#{applicationProperties['security.rememberMeServices.key']}" />
<!-- custom authentication processing filter that accepts json credentials -->
<bean id="authenticationProcessingFilter" class="com.myProject.security.AuthenticationProcessingFilter">
<constructor-arg value="/login" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="rememberMeServices" ref="#{applicationProperties['security.rememberMeServices']}" />
<property name="authenticationSuccessHandler"><bean class="com.myProject.security.AuthenticationSuccessHandler" /></property>
<property name="authenticationFailureHandler"><bean class="com.myProject.security.AuthenticationFailureHandler" /></property>
</bean>
<!-- dummy implementation supplied to satisfy spring-security -->
<bean id="authenticationEntryPoint" class="com.myProject.security.AuthenticationEntryPoint" />
<bean id="logoutSuccessHandler" class="com.myProject.security.LogoutSuccessHandler" />
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
<!-- used by AuthenticationSuccess/FailureHandlers -->
<bean class="org.codehaus.jackson.map.ObjectMapper" />
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000"/>
</bean>
<bean id="legacyAuthenticationProcessingFilter" class="com.myProject.security.LegacyAuthenticationProcessingFilter">
<constructor-arg value="/j_security_check" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler"><bean class="com.myProject.security.AuthenticationSuccessHandler" /></property>
<property name="authenticationFailureHandler"><bean class="com.myProject.security.AuthenticationFailureHandler" /></property>
</bean>
<bean id="legacyLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg ref="logoutSuccessHandler" />
<constructor-arg><bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" /></constructor-arg>
<property name="filterProcessesUrl" value="/Logout.html"></property>
</bean>
</beans>
アップデート
ここに置くには長すぎるため、ログを別の回答として以下に添付します。処理中の別の ajax リクエストがある場合の動作を模倣するために、最初に sleep を呼び出します。ログインが開始される前にこのリクエストを行うことで、このログイン バグを毎回再現することができます。アプリの流れを簡単にまとめると
/スリープ/15000
/blank - これは、Ajax リクエストであるため、ブラウザーがパスワードを保存するように具体的にトリガーするポスト リクエストです。
/login - 実際のログイン スクリプト
/isauthenticated - ユーザーが実際にログインしているかどうかを確認します (アプリケーション固有)
/account/summary - ユーザーの概要を取得します (アプリケーション固有)
/currentuser - 現在のユーザーを取得します (アプリケーション固有)
/sleep/1500 が終了し、セッションがクリアされます。