继续说说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的自问自答,这种精神很想点赞,可惜要登录,要登录就是要FQ,可惜点了半天还没有出来。欲跋千山,涉万水,翻过高墙,穿过荒原,只为跟你说声:谢谢。
http://stackoverflow.com/questions/26041756/concurrency-control-is-not-working


Original url: Access
Created at: 2019-06-24 11:56:25
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论