wuyouzhuguli/SpringAll · warning · LockedAccountException

账号已被锁定,请联系管理员!

Error message

账号已被锁定,请联系管理员!

What it means

LockedAccountException (extends AccountException -> AuthenticationException) is thrown when an account exists and credentials are valid but the account is administratively disabled. Here the gate is user.getStatus().equals("0") - a CHAR(1) status where '0' means locked - and it fires only after both the user lookup and password check pass. The message directs the user to contact an administrator.

Source

Thrown at 13.Spring-Boot-Shiro-Authorization/src/main/java/com/springboot/shiro/ShiroRealm.java:84

	/**
	 * 登录认证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String userName = (String) token.getPrincipal();
		String password = new String((char[]) token.getCredentials());

		System.out.println("用户" + userName + "认证-----ShiroRealm.doGetAuthenticationInfo");
		User user = userMapper.findByUserName(userName);

		if (user == null) {
			throw new UnknownAccountException("用户名或密码错误!");
		}
		if (!password.equals(user.getPassword())) {
			throw new IncorrectCredentialsException("用户名或密码错误!");
		}
		if (user.getStatus().equals("0")) {
			throw new LockedAccountException("账号已被锁定,请联系管理员!");
		}
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
		return info;
	}

}

View on GitHub (pinned to 614d2578d9)

Solutions

  1. Unlock the account in the DB: UPDATE T_USER SET STATUS='1' WHERE USERNAME='<user>'; (STATUS CHAR(1): '1'=active, '0'=locked).
  2. Use the active seeded account 'mrbird' (STATUS='1') instead of 'test' (STATUS='0', locked).
  3. Confirm init.sql seeds STATUS correctly; do not default new accounts to '0'.
  4. Provide an admin unlock screen/API so locked accounts can be re-enabled operationally.

Example fix

-- before: account is locked
SELECT username, status FROM t_user WHERE username = 'test';
-- status = '0'
-- after: unlock the account (STATUS CHAR(1): 1 = active)
UPDATE t_user SET status = '1' WHERE username = 'test';
COMMIT;
Defensive patterns

Strategy: try-catch

Validate before calling

// Optional pre-check of status (after existence confirmed) to fail fast
User u = userMapper.findByUserName(username);
if (u != null && "0".equals(u.getStatus())) {
    return ResponseBo.error("账号已被锁定,请联系管理员!");
}

Type guard

static boolean isActive(User u) {
    return u != null && "1".equals(u.getStatus());
}

Try / catch

try {
    SecurityUtils.getSubject().login(
        new UsernamePasswordToken(username, password));
} catch (LockedAccountException e) {
    return ResponseBo.error("账号已被锁定,请联系管理员!");
} catch (AuthenticationException e) {
    return ResponseBo.error("用户名或密码错误!");
}

Prevention

When it happens

Trigger: Logging in with a correct username AND correct password, but the T_USER row has STATUS='0' in the database (set by the seed - the 'test' account - manually, or flipped by lockout logic). Because this check runs after the credential check, an incorrect password masks the locked state. Context: the authorization (@RequiresRoles/@RequiresPermissions) module.

Common situations: A role/permission test account was seeded with STATUS='0'; even valid credentials cannot reach the authorization layer.

Related errors


AI-assisted analysis of wuyouzhuguli/SpringAll@614d2578d9 (2026-08-14). Data as JSON: /api/errors/dfdf66fe271bb8f2. Report an issue: GitHub.