在完成spring基础配置之后,可以在配置限制单个用户只能一处登录应用程序的功能,Spring Security支持这种开箱即用的功能。
第一步:配置ConcurrentSessionFilter,用来判断session是否过期以及更新最新访问时间;
在配置收到HTTP请求时的安全验证中添加以下配置:
<custom-filter ref="concurrencySessionFilter" position="CONCURRENT_SESSION_FILTER"/>
并配置相应的<b:bean>
<b:bean id="concurrencySessionFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter"> <b:constructor-arg name="sessionRegistry" ref="sessionRegistry" /> <b:constructor-arg name="expiredUrl" value="/login.html" /> </b:bean>
第二步:注入SessionAuthenticationStrategy到CustomUsernamePasswordAuthenticationFilter中,否则默认使用的是NullAuthenticatedSessionStrategy,则获取不到登录用户数;
<!--自定义实现用户名密码及验证码判断功能的Filter,因为用户认证模块涉及了验证码,所以单独写了一个filter,这里这个类就只起了比对用户密码的功能 -->
<b:bean id="customUsernamePasswordAuthenticationFilter" class="cn.topcheer.common.authority.springsec.CustomUsernamePasswordAuthenticationFilter">
<b:property name="enableValidateCode" value="false"></b:property>
<b:property name="authenticationManager" ref="authenticationManager"></b:property>
<b:property name="authenticationFailureHandler" ref="failureHandler"></b:property>
<b:property name="authenticationSuccessHandler" ref="successHandler"></b:property>
<!--注入sessionAuthenticationStrategy-->
<b:property name="sessionAuthenticationStrategy" ref="sas"/>
</b:bean>
其中“sas”配置为:
<b:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy"> <b:constructor-arg> <b:list> <!-- 并行控制 --> <b:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy"> <b:constructor-arg ref="sessionRegistry" /> <b:property name="maximumSessions" value="1" /> <!--控制第二次登录将把第一次登录的用户踢下线--> <b:property name="exceptionIfMaximumExceeded" value="false" /> </b:bean> <b:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" /> <b:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy"> <b:constructor-arg ref="sessionRegistry" /> </b:bean> </b:list> </b:constructor-arg> </b:bean>“sessionRegistry”配置为:
<b:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
配置完成后,重跑程序发现功能并没有实现,在调试过程中发现,判断当前用户是否重复时,这里的sessionCount总是0
于是,我点开sessionReistry.getAllSessions方法
发现这里取principle是根据HashMap取值的,hashMap判断相等需要hashCode相同,因此两个相同用户登录的时候需要相同的hashCode。在实现userDetails接口的用户信息中添加以下代码
扫描二维码关注公众号,回复:
963000 查看本文章
/** * 当同一用户登录多次时,获取的用户不是同一个用户 * 所以需要重写hashcode和equals方法 */ @Override public boolean equals(Object rhs) { if (rhs instanceof CustomSecurityUser) { return getUsername().equals(((CustomSecurityUser) rhs).getUsername()); } return false; } @Override public int hashCode() { return getUsername().hashCode(); }