当前位置 博文首页 > 程序员石磊:spring security 个性化登录策略

    程序员石磊:spring security 个性化登录策略

    作者:[db:作者] 时间:2021-08-08 19:18

    最近做一个项目,安全框架采用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);
            }
    
        }
    
    }

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

    cs
    下一篇:没有了