Springboot +spring session,实现session并发控制

1.配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;

@Configuration
public class HttpSessionConfig {

    @SuppressWarnings("all")
    @Bean
    public SpringSessionBackedSessionRegistry springSessionBackedSessionRegistry(
            FindByIndexNameSessionRepository sessionRepository) {
        return new SpringSessionBackedSessionRegistry(sessionRepository);
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
}
@Resource
private SpringSessionBackedSessionRegistry<?> springSessionBackedSessionRegistry;


http.sessionManagement()
                    .maximumSessions(1)
                    .sessionRegistry(springSessionBackedSessionRegistry)
                    .expiredSessionStrategy(event -> {
                        HttpServletResponse response = event.getResponse();
                        PublicUtil.responseByJSON(RespUtil.error(ResultCodeEnum.USER_NOT_LOGIN.getCode(), ResultCodeEnum.USER_NOT_LOGIN.getMsg()), response);
                    })
            ;

由于是自定义登录,需要设置在AuthenticationManager成功处理身份验证请求后立即调用的会话处理策略。如果没有设置,默认使用空实现,会导致并发控制不生效

2. 根据指定用户名踢人下线



import cn.anicert.basconsole.core.dao.xtgl.SysUserMapper;
import cn.anicert.basconsole.core.util.FutureUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.function.Supplier;

@Component
public class UserUtils {
    private static FindByIndexNameSessionRepository<Session> sessionRepository;
    private static SysUserMapper sysUserMapper;

    private static boolean enable;


    @Autowired
    @SuppressWarnings("all")
    public UserUtils(FindByIndexNameSessionRepository sessionRepository, SysUserMapper sysUserMapper) {
        UserUtils.sessionRepository = sessionRepository;
        UserUtils.sysUserMapper = sysUserMapper;
    }

    /**
     * 根据指定用户名退出登录
     *
     * @param supplier 用户名
     */
    public static void expireNowByUserName(Supplier<List<String>> supplier) {

        if (!enable) {
            return;
        }

        FutureUtils.runAsync(() -> {
            List<String> userNames = supplier.get();
            if (CollectionUtils.isEmpty(userNames)) {
                return;
            }

            for (String userName : userNames) {
                sessionRepository.findByPrincipalName(userName)
                        .forEach((k, session) -> sessionRepository.deleteById(session.getId()));
            }

        });
    }

    public static void expireNowByRoleId(String roleId) {
        expireNowByUserName(() -> sysUserMapper.selectNameByRoleId(roleId));
    }

    public static void expireNowByMenuId(Integer menuId) {
        expireNowByUserName(() -> sysUserMapper.selectNameByMenuId(menuId));
    }


    @Value("${cc.security.session.expire.enable}")
    public void setEnable(boolean enable) {
        UserUtils.enable = enable;
    }
}

3. 自定义当前主体名称(即用户名)的会话索引

默认是username,但是我们项目的用户名是可以重复的,所以踢人下线用用户名就有问题。

在登录成功的地方,设置一下即可。

HttpSession session = request.getSession();
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,sysuser.getLoginName());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值