{"record":{"id":"c9343b53069a75f1","repo":"xkcoding/spring-boot-demo","slug":"5004","errorCode":"5004","errorMessage":"无法手动踢出自己，请尝试退出登录操作！","messagePattern":"无法手动踢出自己，请尝试退出登录操作！","errorType":"exception","errorClass":"SecurityException","httpStatus":null,"severity":"info","filePath":"demo-rbac-security/src/main/java/com/xkcoding/rbac/security/controller/MonitorController.java","lineNumber":57,"sourceCode":"    @GetMapping(\"/online/user\")\n    public ApiResponse onlineUser(PageCondition pageCondition) {\n        PageUtil.checkPageCondition(pageCondition, PageCondition.class);\n        PageResult<OnlineUser> pageResult = monitorService.onlineUser(pageCondition);\n        return ApiResponse.ofSuccess(pageResult);\n    }\n\n    /**\n     * 批量踢出在线用户\n     *\n     * @param names 用户名列表\n     */\n    @DeleteMapping(\"/online/user/kickout\")\n    public ApiResponse kickoutOnlineUser(@RequestBody List<String> names) {\n        if (CollUtil.isEmpty(names)) {\n            throw new SecurityException(Status.PARAM_NOT_NULL);\n        }\n        if (names.contains(SecurityUtil.getCurrentUsername())) {\n            throw new SecurityException(Status.KICKOUT_SELF);\n        }\n        monitorService.kickout(names);\n        return ApiResponse.ofSuccess();\n    }\n}\n","sourceCodeStart":39,"sourceCodeEnd":63,"githubUrl":"https://github.com/xkcoding/spring-boot-demo/blob/87a142f9604c1a5365b4d24d22c2c11c26a9d5ab/demo-rbac-security/src/main/java/com/xkcoding/rbac/security/controller/MonitorController.java#L39-L63","documentation":"Thrown by the kickout endpoint when the names list contains the currently authenticated user's own username. SecurityUtil.getCurrentUsername() retrieves the caller's identity from the security context; if it appears in the kickout list, Status.KICKOUT_SELF (code 5004) is thrown. This is a business-logic guard preventing self-session-termination via the admin kickout path (which would bypass proper logout).","triggerScenarios":"An authenticated admin sends DELETE /api/monitor/online/user/kickout with their own username included in the names array. names.contains(SecurityUtil.getCurrentUsername()) returns true.","commonSituations":"Admin accidentally selects themselves in a multi-select user list; the UI does not exclude the current user from the kickout target list; automated script that kicks all online users including the script's own session.","solutions":["Exclude the current user from the kickout selection in the frontend UI.","On the client, filter out SecurityUtil.getCurrentUsername() from the names list before sending.","Handle the 5004 response code by showing a message like 'you cannot kick yourself out, use logout instead'."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Filter out the current user from the kickout list before sending\nString currentUser = SecurityUtil.getCurrentUsername();\nList<String> filteredNames = names.stream()\n    .filter(name -> !name.equals(currentUser))\n    .collect(Collectors.toList());\nif (filteredNames.isEmpty()) {\n    // All selected users were the current user — inform and abort\n    return ResponseEntity.badRequest().body(\"Cannot kick out yourself\");\n}","typeGuard":null,"tryCatchPattern":"// In a @ControllerAdvice handler for SecurityException\n@ExceptionHandler(SecurityException.class)\n@ResponseBody\npublic ResponseEntity<ApiResponse> handleSecurityException(SecurityException e) {\n    Status status = e.getStatus();\n    if (status.getCode() == 5004) {\n        return ResponseEntity.status(HttpStatus.BAD_REQUEST)\n            .body(ApiResponse.ofStatus(Status.KICKOUT_SELF));\n    }\n    return ResponseEntity.status(500).body(ApiResponse.ofStatus(Status.ERROR));\n}","preventionTips":["Exclude the current user from the kickout selection list in the frontend UI.","Filter out the current username from the names array client-side before sending.","Show a user-friendly message when code 5004 is returned."],"tags":["spring-security","rbac","business-logic","session-management","monitor","self-operation-guard"],"backgroundTag":null,"analyzedSha":"87a142f9604c1a5365b4d24d22c2c11c26a9d5ab","analyzedAt":"2026-08-14T01:16:58.217Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}