建议先看完spring security的基础配置,再看下面的配置流程就会很明白了。
https://blog.csdn.net/u013984781/article/details/79755131
在完成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>
<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接口的用户信息中添加以下代码
/**
* 当同一用户登录多次时,获取的用户不是同一个用户
* 所以需要重写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();
}