zoukankan      html  css  js  c++  java
  • 继续说说spring security之并发控制(Concurrency Control)

    定义,作用,说明:

    Concurrency Control:并发控制,主要用于避免同一用户多次登录,重复登录以及包括相关的session管理--具体官网---》

    先看官网:http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#session-mgmt

    官网的并发控制已经说得比较清楚,但是偏偏有人(例如我)重写了(自定义了)验证的方法,导致了失效的问题,至此,一起说说spring security之并发控制配置以及相关编写:

    分为三种方式:

    基本配置:

    web.xml 加入监听

    <listener>
      <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
      </listener-class>
    </listener>

    第一种,入门试(简单配置)没有自定义了spring security验证的

    <http>
      ...
      <session-management>
         <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
      </session-management>
    </http>

    或者

    <http>
      ...
      <session-management>
         <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
      </session-management>
    </http>

    区别在于前者剔除上一个用户,后者第二个不给登录

    记住前提:没有自定义验证方法,官网:

    If you are using a customized authentication filter for form-based login, then you have to configure concurrent session control support explicitly. More details can be found in the Session Management chapter.

    但如果自定义了自定义的UserDetails 则需要重定义equal和hashcode

    第二种方法:

    打开官网其实已经说得很清楚了。。。。

    还不清楚再看来自iteye的网友 http://sb33060418.iteye.com/blog/1953515 

    第三种方法(我就是用这种。。。)

    首先看看我的验证(使用程序的方法去调用,很大限度的自定义了验证)

        public LoginInfo login(@RequestParam(defaultValue="") String username,@RequestParam(defaultValue="") String password,HttpServletRequest request,HttpServletResponse response){
            if(!checkValidateCode(request)){
                return new LoginInfo().failed().msg("验证码错误!");
            }
            username = username.trim();
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
    /*        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(CwSysUser.class,"cwSysUser");
            detachedCriteria.add(Restrictions.eq("userNo", username));
            if(cwSysUserService.countUser(detachedCriteria)==0){
                return new LoginInfo().failed().msg("用户名: "+username+" 不存在.");
            }
    */        try {
                Authentication authentication = myAuthenticationManager.authenticate(authRequest); //调用loadUserByUsername
                SecurityContextHolder.getContext().setAuthentication(authentication);
                HttpSession session = request.getSession();
                session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext()); // 这个非常重要,否则验证后将无法登陆
                sas.onAuthentication(authentication, request, response);
                return new LoginInfo().success().msg(authentication.getName());
            }catch (AuthenticationException ex) {
                if(ex.getMessage()==null){
                    return new LoginInfo().failed().msg("用户名不存在.");
                }
                return new LoginInfo().failed().msg("用户名或密码错误");
            }
        } 
        

    说明:

    Authentication authentication = myAuthenticationManager.authenticate(authRequest); //这里就是在程序中用
    myAuthenticationManager调用了验证信息,基于myAuthenticationManager在下面xml的配置重新写了loadUserByUsername方法
     sas.onAuthentication(authentication, request, response);// 这里就是手动调用了并发控制(在xml做了注入配置)

    配置spring-security.xml (配置基本和二差不错,但是少了自定义登录拦截配置)

        <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
            <session-management
                session-authentication-strategy-ref="sas" />
        </http>
    
        <beans:bean id="concurrencyFilter"
            class="org.springframework.security.web.session.ConcurrentSessionFilter">
            <beans:property name="sessionRegistry" ref="sessionRegistry" />
            <beans:property name="expiredUrl" value="/session-expired.htm" />
        </beans:bean>
    
        <beans:bean id="sas"
            class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
            <beans:constructor-arg>
                <beans:list>
                    <beans:bean
                        class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
                        <beans:constructor-arg ref="sessionRegistry" />
                        <beans:property name="maximumSessions" value="1" />
                    </beans:bean>
                    <beans:bean
                        class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
                    </beans:bean>
                    <beans:bean
                        class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
                        <beans:constructor-arg ref="sessionRegistry" />
                    </beans:bean>
                </beans:list>
            </beans:constructor-arg>
        </beans:bean>
    
        <beans:bean id="sessionRegistry"
            class="org.springframework.security.core.session.SessionRegistryImpl" />
    
        <authentication-manager alias="myAuthenticationManager">
            <authentication-provider user-service-ref="cwSysUserDetailsService">  <!-- 数据库提供者 -->
                <password-encoder hash="md5"></password-encoder>
            </authentication-provider>
        </authentication-manager>

    至此,完成。。。。。

    非常感谢:stackoverflow和ma4的自问自答,这种精神很想点赞,可惜要登录,要登录就是要翻墙,可惜点了半天还没有出来。欲跋千山,涉万水,翻过高墙,穿过荒原,只为跟你说声:谢谢。

    http://stackoverflow.com/questions/26041756/concurrency-control-is-not-working

  • 相关阅读:
    《入门经典》——6.15
    《Linear Algebra and Its Application》-chaper1-行化简法解决线性方程组
    《算法实战策略》-chaper19-队列、栈和双端队列
    《Linear Algebra and Its Applications》-chaper1-向量方程、矩阵方程和线性方程组
    辛普森法则
    《训练指南》——6.15
    《入门经典》——6.21
    《算法问题实战策略》-chaper13-数值分析
    Scheme 中的 pair 和 list 简述
    C. Friends
  • 原文地址:https://www.cnblogs.com/huangjiandong2012/p/4040030.html
Copyright © 2011-2022 走看看