spring security 个性化登录策略

来源:互联网 发布:seo搜索排名优化怎么 编辑:程序博客网 时间:2024/06/01 07:56

最近做一个项目,安全框架采用spring security 。由于业务需要,要限制一个账户只能登录一次,不能在多个浏览器登录,也就是一个账户只能对应一个sessionid。这个很好实现,配置上默认的 session并发策略ConcurrentSessionControlAuthenticationStrategy类,设置maximumSessions值为1。代码如下:

<sec:http use-expressions="false" auto-config="true">        <sec:session-management invalid-session-url="/sessionexpired" session-authentication-strategy ref="sas" />    </sec:http><bean id="sas"        class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">        <constructor-arg>            <list>                <bean                    class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">                    <constructor-arg ref="sessionRegistry" />                    <property name="maximumSessions" value="1" />                    <property name="exceptionIfMaximumExceeded" value="false" />                </bean>            </list>        </constructor-arg>    </bean>

但是这样如果账户a在一个地方登录,然后又换另外一个地方登录,后登录的会导致前一个用户session失效,也就是会踢掉前面登录的用户。这样是不允许的,而需要要求是,可以根据用户某个状态来判断,如果用户处在空闲状态,就允许同一个账号后登录的踢掉前面登录的,如果是繁忙状态就不允许登录。经过研究ConcurrentSessionControlAuthenticationStrategy类的源码,获得灵感,自定义一个SessionAuthenticationStrategy的实现类CloudqControlAuthenticationStrategy,里面增加状态判断,如果不满足条件就抛出异常,问题就可以解决了。配置代码如下:

<bean id="sas"        class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">        <constructor-arg>            <list>                    <bean                    class="com.raymon.cloudq.security.CloudqControlAuthenticationStrategy">                </bean>                <bean                    class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">                    <constructor-arg ref="sessionRegistry" />                    <property name="maximumSessions" value="1" />                    <property name="exceptionIfMaximumExceeded" value="false" />                </bean>            </list>        </constructor-arg>    </bean>

自定义策略代码:

public class CloudqControlAuthenticationStrategy implements SessionAuthenticationStrategy {    private org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());    @Override    public void onAuthentication(Authentication authentication, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)  throws SessionAuthenticationException  {        AuthUserDetails authUserDetails=(AuthUserDetails)authentication.getPrincipal();        Integer branchesId=authUserDetails.getClientEmpUser().getBranchesId();        Integer empId=authUserDetails.getClientEmpUser().getEmpId();        if(条件不满足){//抛出异常            throw new SessionAuthenticationException(message);        }    }}

注意自定义策略的放置顺序要在其他策略前面,否则可能会造成自己的业务逻辑执行过晚,进而达不到目的。

原创粉丝点击