天天看点

设置1个账号不能同时在2台电脑登录

案例1:当用户在第2台电脑登录时,第1台电脑抛出错误信息,并下线

  • 在security配置类中添加如下
.and()
.sessionManagement()// session管理
// 设置最大session数量为1
.maximumSessions(1)      
  • 测试1:用edge浏览器模拟第1台电脑,用谷歌浏览器模拟第2台电脑,在edge浏览器认证成功后,再去谷歌浏览器认证,谷歌浏览器认证成功后,刷新edge浏览器,提示如下错误信息
  • 设置1个账号不能同时在2台电脑登录
  • 自定义错误信息
  • 编写处理类
public class CustomSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {

    // 注入认证失败的处理器
    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException {
        // 1. 获取用户名
        UserDetails userDetails =
                (UserDetails)event.getSessionInformation().getPrincipal();
        // 定义错误信息
        AuthenticationException exception =
                new AuthenticationServiceException(
                        String.format("[%s] 用户在另外一台电脑登录,您已被下线", userDetails.getUsername()));
        try {
            // 当用户在多台电脑登录后,设置1个状态为true
            event.getRequest().setAttribute("toAuthentication" , true);
            // 将异常信息传给认证失败处理器
            customAuthenticationFailureHandler
                    .onAuthenticationFailure(event.getRequest(), event.getResponse(), exception);
        } catch (ServletException e) {
            e.printStackTrace();
        }
    }
    
}      
  • 配置失败处理器
@Component("customAuthenticationFailureHandler")
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    /**
     * @param exception 认证失败时抛出异常
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        // 认证失败响应JSON字符串,
        MengxueguResult result = MengxueguResult.build(HttpStatus.UNAUTHORIZED.value(), exception.getMessage());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(result.toJsonString());
        System.out.println("CustomAuthenticationFailureHandler ---> error");
        // 如果下面有值,则认为是多端登录,则抛出多端登录的异常;否则抛出认证失败的异常
        Object toAuthentication = request.getAttribute("toAuthentication");
        if (toAuthentication != null) {
            error1();
        } else {
            error2();
        }
    }

    public void error1() {
        System.out.println("当前为用户在多台电脑登录抛出的异常!");
    }

    public void error2() {
        System.out.println("当前为用户认证失败抛出的异常!");
    }

}      
  • 配置管理容器
@Configuration
public class SecurityConfigBean {

    /**
     * 当有其他类实现SessionInformationExpiredStrategy接口时,并添加@Component注解时
     * 则使用其他类作为session超出最大限制的处理
     * 没有其他类实现时
     * 则默认使用CustomSessionInformationExpiredStrategy处理session超出最大限制的处理
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(SessionInformationExpiredStrategy.class)
    public SessionInformationExpiredStrategy sessionInformationExpiredStrategy() {
        return new CustomSessionInformationExpiredStrategy();
    }

}      
  • 配置security配置类
// 注入
@Autowired
private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;

// 配置
.and()
.sessionManagement()// session管理
// 设置最大session数量为1
.maximumSessions(1)
// 设置超过最大session数量后的处理
.expiredSessionStrategy(sessionInformationExpiredStrategy)      
  • 测试2:用edge浏览器模拟第1台电脑,用谷歌浏览器模拟第2台电脑,在edge浏览器认证成功后,再去谷歌浏览器认证,谷歌浏览器认证成功后,刷新edge浏览器,提示如下错误信息
  • 设置1个账号不能同时在2台电脑登录
# 控制台打印入下
11:55:13.397  INFO 19888 --- [nio-8080-exec-4] c.y.s.service.CustomUserDetailsService   : 请求认证的用户名: admin
CustomAuthenticationFailureHandler ---> error
当前为用户在多台电脑登录抛出的异常!      
  • 测试认证失败:认证时输入错误的用户名和密码
  • 设置1个账号不能同时在2台电脑登录
# 控制台打印如下
12:12:51.770  INFO 19888 --- [nio-8080-exec-8] c.y.s.service.CustomUserDetailsService   : 请求认证的用户名: admin
CustomAuthenticationFailureHandler ---> error
当前为用户认证失败抛出的异常!      

案例2:当用户在第1台电脑认证成功后,再在第2台电脑登录,这是不允许在第2台电脑登录

  • ​使用记住我功能时,不能设置maxSessionsPreventsLogin(true)​

  • 在security配置类中配置如下
.and()
.sessionManagement()// session管理
// 设置最大session数量为1
.maximumSessions(1)
// 设置超过最大session数量后的处理
.expiredSessionStrategy(sessionInformationExpiredStrategy)// 当用户达到最大session数后,则调用此处的实现
.maxSessionsPreventsLogin(true)  // 当一个用户达到最大session数,则不允许后面再登录      
  • 测试:在edge浏览器认证成功,之后在联想浏览器认证
# 控制台打印如下
13:14:04.169  INFO 23736 --- [nio-8080-exec-9] c.y.s.service.CustomUserDetailsService   : 请求认证的用户名: admin
CustomAuthenticationFailureHandler ---> error
当前为用户认证失败抛出的异常!      

案例3:只允许1台电脑登录;第1台电脑使用用户名+密码登录,设置第2台电脑不能使用用户名+密码或手机号+短信

  • 如果在当前项目中可以使用用户名+密码认证,也可以使用手机号+验证码认证;在设置了不允许第2台电脑登录的情况下,第1台电脑使用用户名+密码认证,第2台电脑使用手机号+短信认证也能认证,正确逻辑是第2台电脑既不能使用用户名+密码认证,也不能使用手机号+短信认证,说明之前设置的只允许1台电脑登录无效
# 在MobileAuthenticationConfig中配置如下
// session重复登录 管理
mobileAuthenticationFilter.setSessionAuthenticationStrategy(http.getSharedObject(SessionAuthenticationStrategy.class));      

继续阅读