{"record":{"id":"2178696b72200838","repo":"jeecgboot/JeecgBoot","slug":"error-217869","errorCode":null,"errorMessage":"账号已被锁定,请联系管理员!","messagePattern":"账号已被锁定,请联系管理员!","errorType":"exception","errorClass":"AuthenticationException","httpStatus":401,"severity":"error","filePath":"jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java","lineNumber":140,"sourceCode":"     * @param token\n     */\n    public LoginUser checkUserTokenIsEffect(String token) throws AuthenticationException {\n        // 解密获得username，用于和数据库进行对比\n        String username = JwtUtil.getUsername(token);\n        if (username == null) {\n            throw new AuthenticationException(\"Token非法无效!\");\n        }\n\n        // 查询用户信息\n        log.debug(\"———校验token是否有效————checkUserTokenIsEffect——————— \"+ token);\n        LoginUser loginUser = TokenUtils.getLoginUser(username, commonApi, redisUtil);\n        //LoginUser loginUser = commonApi.getUserByName(username);\n        if (loginUser == null) {\n            throw new AuthenticationException(\"用户不存在!\");\n        }\n        // 判断用户状态\n        if (loginUser.getStatus() != 1) {\n            throw new AuthenticationException(\"账号已被锁定,请联系管理员!\");\n        }\n        // 校验token是否超时失效 & 或者账号密码是否错误\n        if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {\n            // 用户登录Token过期提示信息\n            String userLoginTokenErrorMsg = oConvertUtils.getString(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN_ERROR_MSG + token));\n            throw new AuthenticationException(oConvertUtils.isEmpty(userLoginTokenErrorMsg)? CommonConstant.TOKEN_IS_INVALID_MSG: userLoginTokenErrorMsg);\n        }\n        // 代码逻辑说明: 校验用户的tenant_id和前端传过来的是否一致\n        String userTenantIds = loginUser.getRelTenantIds();\n        if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL && oConvertUtils.isNotEmpty(userTenantIds)){\n            String contextTenantId = TenantContext.getTenant();\n            log.debug(\"登录租户：\" + contextTenantId);\n            log.debug(\"用户拥有那些租户：\" + userTenantIds);\n             //登录用户无租户，前端header中租户ID值为 0\n            String str =\"0\";\n            if(oConvertUtils.isNotEmpty(contextTenantId) && !str.equals(contextTenantId)){\n                // 代码逻辑说明: /issues/I4O14W 用户租户信息变更判断漏洞\n                String[] arr = userTenantIds.split(\",\");","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java#L122-L158","documentation":"Thrown by ShiroRealm.checkUserTokenIsEffect() when loginUser.getStatus() != 1 — the user account exists but is disabled/locked. Status 1 means active; any other value (commonly 2 for locked, 0 for disabled) triggers this exception. This is an intentional security control to prevent locked users from maintaining active sessions.","triggerScenarios":"Admin locks or disables a user account while that user has an active session; user account was auto-locked after too many failed login attempts; batch user status update deactivated the account.","commonSituations":"Security policy locks accounts after N failed attempts; admin deactivates a departing employee's account; scheduled job bulk-disables accounts; user's status was changed via direct database update without clearing their Redis token cache.","solutions":["Administrator unlocks the account: set sys_user.status = 1 via the user management UI or SQL.","Clear the user's cached token from Redis (PREFIX_USER_TOKEN + token key) after status change.","Review the failed login attempt policy if accounts are being locked too aggressively.","For the affected user: after unlock, log out and log in again."],"exampleFix":"-- Unlock the user account\nUPDATE sys_user SET status = 1 WHERE username = '<username>';\n-- Clear stale token cache (find token key pattern in Redis)\n-- redis-cli: DEL \"PREFIX_USER_TOKEN:<token>\"\n-- Then user logs out and logs in again.","handlingStrategy":"try-catch","validationCode":"// Admin should verify user status before users attempt access\n// SELECT username, status FROM sys_user WHERE username = '<username>'\n// If status != 1, unlock: UPDATE sys_user SET status = 1 WHERE username = '<username>'","typeGuard":null,"tryCatchPattern":"// Handled by JwtFilter — returns 401 with '账号已被锁定'\n// Front-end: show lock message and redirect to login\naxios.interceptors.response.use(null, error => {\n    if (error.response?.data?.message?.includes('锁定')) {\n        notification.error({ message: '账号已被锁定，请联系管理员' });\n        router.push('/user/login');\n    }\n});","preventionTips":["When locking a user account, clear their token from Redis to immediately invalidate sessions.","Review failed-login lockout policies to avoid overly aggressive auto-locking.","After unlocking, have the user re-authenticate."],"tags":["shiro","jwt","authentication","account-locked","user-status"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}