繼續說說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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM