Spring Security 3.1.x并发控制:ConcurrentSessionFilter配置疑问
Hey there! Since you're new to Spring Security, let me walk you through the key implementation points for setting up ConcurrentSessionFilter (as covered in the 3.1.x concurrency control chapter) clearly. This setup relies on a few core components working together, so I'll break it down step by step:
1. Core Components to Understand
First, let's recap the key pieces you'll need to make this work:
SessionRegistryImpl: The default implementation ofSessionRegistry, which tracks all active user sessions in your application. It's the backbone for monitoring concurrent logins.ConcurrentSessionFilter: The filter that checks if a user's session has expired (due to exceeding concurrent login limits) on every request, and redirects to yourexpiredUrlif so.ConcurrentSessionControlStrategy: Handles concurrency rules during authentication (e.g., how many concurrent logins are allowed per user, what happens when the limit is hit).
2. Step-by-Step Configuration (XML, since 3.1.x relies heavily on it)
a. Define the SessionRegistry Bean
You need a single, shared instance of SessionRegistryImpl across your app—this ensures all session data is tracked in one place:
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
b. Configure the ConcurrentSessionFilter
Inject the sessionRegistry and set your expiredUrl (the page users land on when their session is expired due to concurrency):
<bean id="concurrentSessionFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter"> <!-- Constructor args: first is the SessionRegistry, second is your expired page URL --> <constructor-arg ref="sessionRegistry" /> <constructor-arg value="/session-expired" /> <!-- Replace with your actual expired page path --> </bean>
c. Add the Filter to the Security Filter Chain
Filter order is critical here—use Spring's built-in position constant to ensure the filter is placed correctly in the chain:
<http auto-config="false" use-expressions="true"> <!-- Your existing URL access rules --> <intercept-url pattern="/session-expired" access="permitAll" /> <!-- Ensure expired page is accessible anonymously --> <intercept-url pattern="/**" access="isAuthenticated()" /> <!-- Insert ConcurrentSessionFilter into the chain at the correct position --> <custom-filter ref="concurrentSessionFilter" position="CONCURRENT_SESSION_FILTER" /> <!-- Link session management to your concurrency control strategy --> <session-management session-authentication-strategy-ref="concurrentSessionControlStrategy" /> </http>
d. Set Up the ConcurrentSessionControlStrategy
This bean enforces your concurrency rules when a user logs in. Define how many concurrent sessions are allowed and what happens when the limit is exceeded:
<bean id="concurrentSessionControlStrategy" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"> <constructor-arg ref="sessionRegistry" /> <property name="maximumSessions" value="1" /> <!-- Allow only 1 concurrent login per user --> <property name="exceptionIfMaximumExceeded" value="true" /> <!-- Reject new login if limit is hit (instead of expiring old session) --> </bean>
e. Add HttpSessionEventPublisher to web.xml
This listener ensures Spring Security is notified when sessions are destroyed (e.g., via timeout or logout), so the SessionRegistry stays updated with accurate session data:
<web-app> <!-- Other web.xml configuration --> <listener> <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> </listener> </web-app>
3. Critical Implementation Notes
- Filter Order: Using
position="CONCURRENT_SESSION_FILTER"guarantees the filter runs afterSecurityContextPersistenceFilter(so it can access the current user's security context) and before authentication filters likeUsernamePasswordAuthenticationFilter—this is the correct order for it to function as intended. - Anonymous Access for expiredUrl: Always configure your
expiredUrlpath to allow unauthenticated access (viaaccess="permitAll"), otherwise users will hit an access denied error instead of your expired page. - Concurrency Rule Flexibility:
- If you set
exceptionIfMaximumExceeded="false", new logins will expire the oldest existing session for the user instead of being rejected. - Adjust
maximumSessionsto match your app's needs (e.g.,2if you allow users to log in from two devices at once).
- If you set
- Single SessionRegistry Instance: Never create multiple
SessionRegistryImplbeans—this will break session tracking, as each instance would maintain separate session data.
内容的提问来源于stack exchange,提问作者Abdu Manas C A

