天天看點

設定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));      

繼續閱讀