xkcoding/spring-boot-demo · info · SecurityException

5004

5004

Error message

无法手动踢出自己,请尝试退出登录操作!

What it means

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).

Source

Thrown at demo-rbac-security/src/main/java/com/xkcoding/rbac/security/controller/MonitorController.java:57

    @GetMapping("/online/user")
    public ApiResponse onlineUser(PageCondition pageCondition) {
        PageUtil.checkPageCondition(pageCondition, PageCondition.class);
        PageResult<OnlineUser> pageResult = monitorService.onlineUser(pageCondition);
        return ApiResponse.ofSuccess(pageResult);
    }

    /**
     * 批量踢出在线用户
     *
     * @param names 用户名列表
     */
    @DeleteMapping("/online/user/kickout")
    public ApiResponse kickoutOnlineUser(@RequestBody List<String> names) {
        if (CollUtil.isEmpty(names)) {
            throw new SecurityException(Status.PARAM_NOT_NULL);
        }
        if (names.contains(SecurityUtil.getCurrentUsername())) {
            throw new SecurityException(Status.KICKOUT_SELF);
        }
        monitorService.kickout(names);
        return ApiResponse.ofSuccess();
    }
}

View on GitHub (pinned to 87a142f960)

Solutions

  1. Exclude the current user from the kickout selection in the frontend UI.
  2. On the client, filter out SecurityUtil.getCurrentUsername() from the names list before sending.
  3. Handle the 5004 response code by showing a message like 'you cannot kick yourself out, use logout instead'.
Defensive patterns

Strategy: validation

Validate before calling

// Filter out the current user from the kickout list before sending
String currentUser = SecurityUtil.getCurrentUsername();
List<String> filteredNames = names.stream()
    .filter(name -> !name.equals(currentUser))
    .collect(Collectors.toList());
if (filteredNames.isEmpty()) {
    // All selected users were the current user — inform and abort
    return ResponseEntity.badRequest().body("Cannot kick out yourself");
}

Try / catch

// In a @ControllerAdvice handler for SecurityException
@ExceptionHandler(SecurityException.class)
@ResponseBody
public ResponseEntity<ApiResponse> handleSecurityException(SecurityException e) {
    Status status = e.getStatus();
    if (status.getCode() == 5004) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body(ApiResponse.ofStatus(Status.KICKOUT_SELF));
    }
    return ResponseEntity.status(500).body(ApiResponse.ofStatus(Status.ERROR));
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of xkcoding/spring-boot-demo@87a142f960 (2026-08-14). Data as JSON: /api/errors/c9343b53069a75f1. Report an issue: GitHub.