SpringSecurity+Springboot实现踢掉前一个登录用户

SpringSecurity+Springboot实现踢掉前一个登录用户

1.需求分析

要实现一个用户不可以同时在两台设备上登录,有两种思路:
(1)后来的登录自动踢掉前面的登录,就像大家在扣扣中看到的效果
(2)如果用户已经登录,则不允许后来者登录。
这种思路都能实现这个功能,具体使用哪一个,还要看我们具体的需求。
在 Spring Security 中,这两种都很好实现。
下面只说第一种实现。

2.具体实现

(1)踢掉前面的登录
想要用新的登录踢掉旧的登录,我们只需要将最大会话数设置为 1 即可,配置如下:

	// 关闭csrf验证
	http.csrf().disable().cors()
	       // create no session
	       .and()
	       .sessionManagement()
	       .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
	       // session 已经过期的提示解决
           .sessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy())
           // 对请求进行认证
           .and()
           .authorizeRequests()
           .antMatchers(resources).permitAll()
           .antMatchers(HttpMethod.POST, postMapping).permitAll()
           .antMatchers(HttpMethod.GET, getMapping).permitAll()
           // 所有请求需要身份认证
           .anyRequest().authenticated()
           .and()
           .exceptionHandling()
           .authenticationEntryPoint(new Http401AuthenticationEntryPoint())
           .and()
	       .maximumSessions(1)
	       .sessionRegistry(sessionRegistry)
	       .maxSessionsPreventsLogin(false);

maximumSessions 表示配置最大会话数为 1,这样后面的登录就会自动踢掉前面的登录
会有以下提示:
This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).
可以看到,这里说这个 session 已经过期,原因则是由于使用同一个用户进行并发登录
(2)解决 session 已经过期的提示

 .sessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy())

把该类加入到web配置里

public class ConcurrentSessionControlAuthenticationStrategy implements
        MessageSourceAware, SessionAuthenticationStrategy {

    @Autowired
    private SessionRegistry sessionRegistry;

    private MessageSource messageSource;


    public void onAuthentication(Authentication authentication,
                                 HttpServletRequest request, HttpServletResponse response) {
        int sessionCount = 0;
        List<SessionInformation> sessions = new ArrayList<>();
        if (sessionRegistry!=null) {
            sessions = sessionRegistry.getAllSessions(
                    authentication.getPrincipal(), false);
            sessionCount = sessions.size();
        }
        int allowedSessions = 1;

        if (sessionCount < allowedSessions) {
            // They haven't got too many login sessions running at present
            return;
        }

        if (allowedSessions == -1) {
            // We permit unlimited logins
            return;
        }
        if (sessionCount == allowedSessions) {
            HttpSession session = request.getSession(false);

            if (session != null) {
                for (SessionInformation si : sessions) {
                    if (si.getSessionId().equals(session.getId())) {
                        return;
                    }
                }
            }
        }

        allowableSessionsExceeded(sessions, allowedSessions, sessionRegistry);
    }
    protected void allowableSessionsExceeded(List<SessionInformation> sessions,
                                             int allowableSessions, SessionRegistry registry)
            throws SessionAuthenticationException {
        if ((sessions == null)) {
            throw new SessionAuthenticationException(messageSource.getMessage(
                    "ConcurrentSessionControlAuthenticationStrategy.exceededAllowed",
                    new Object[] {allowableSessions},
                    Locale.forLanguageTag("Maximum sessions of {0} for this principal exceeded")));
        }

        sessions.sort(Comparator.comparing(SessionInformation::getLastRequest));
        int maximumSessionsExceededBy = sessions.size() - allowableSessions + 1;
        List<SessionInformation> sessionsToBeExpired = sessions.subList(0, maximumSessionsExceededBy);
        for (SessionInformation session: sessionsToBeExpired) {
            session.expireNow();
        }
    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现用户登录用户添加需要如下步骤: 1. 创建Spring Boot项目 2. 集成Spring Security 3. 创建用户实体类和DAO层 4. 创建用户Service层和Controller层 5. 创建Vue端页面 6. 实现登录用户添加功能 具体步骤如下: 1. 创建Spring Boot项目 可以使用Spring Initializr创建一个Maven项目,添加Web、Spring Security、MyBatis等依赖。 2. 集成Spring SecuritySpring Boot项目中,可以通过添加Spring Security依赖来实现安全认证和授权。在配置类中,可以定义登录页面和权限配置等。 3. 创建用户实体类和DAO层 创建用户实体类,包含用户名和密码等属性。然后创建UserMapper接口,继承MyBatis的Mapper接口,定义查询用户的方法。 4. 创建用户Service层和Controller层 创建UserService接口和UserServiceImpl实现类,定义用户登录和添加用户的方法。然后创建UserController类,处理用户登录用户添加的请求。 5. 创建Vue端页面 使用Vue框架创建端页面,包括登录页面和用户添加页面。 6. 实现登录用户添加功能 在登录页面中,输入用户名和密码,通过axios发送请求到后端UserController中的登录方法进行认证。在用户添加页面中,输入用户信息,通过axios发送请求到后端UserController中的添加用户方法进行添加。 以上就是实现用户登录用户添加的步骤。具体实现过程可以参考相关文档和示例代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值