wuyouzhuguli/SpringAll · error · UnknownAccountException

用户名或密码错误!

Error message

用户名或密码错误!

What it means

Apache Shiro raises UnknownAccountException (extends AccountException -> AuthenticationException) when a Realm's doGetAuthenticationInfo cannot resolve the submitted principal to a stored account. Here userMapper.findByUserName(userName) returns null, so the code throws with the deliberately shared message '用户名或密码错误!' to avoid revealing whether the username exists (anti-user-enumeration). It propagates out of Subject.login(token) up to the login controller.

Source

Thrown at 16.Spring-Boot-Shiro-Thymeleaf-Tag/src/main/java/com/springboot/shiro/ShiroRealm.java:78

			permissionSet.add(p.getName());
		}
		simpleAuthorizationInfo.setStringPermissions(permissionSet);
		return simpleAuthorizationInfo;
	}

	/**
	 * 登录认证
	 */
	@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. Run the module's init.sql in Oracle so the row exists: it seeds T_USER with 'mrbird' (STATUS 1) and 'test' (STATUS 0).
  2. Confirm the datasource is Oracle (init.sql uses VARCHAR2/NUMBER/TO_DATE); check application.yml driver/url and that you are not pointing at MySQL.
  3. Verify UserMapper.xml: findByUserName must read 'select * from t_user where username = #{userName}' (table t_user, column username) and resultMap maps passwd->password, status->status.
  4. Confirm the login form posts field 'username' (LoginController param 'String username'), so token.getPrincipal() is the intended value.

Example fix

// before
User user = userMapper.findByUserName(userName);
if (user == null) {
    throw new UnknownAccountException("用户名或密码错误!");
}
// after - make sure the row exists AND the mapper maps it
// UserMapper.xml:
//   <resultMap type="com.springboot.pojo.User" id="User">
//     <id column="username" property="userName"/>
//     <id column="passwd"   property="password"/>
//     <id column="status"   property="status"/>
//   </resultMap>
//   <select id="findByUserName" resultMap="User">
//     select * from t_user where username = #{userName}
//   </select>
-- init.sql seed (Oracle):
-- INSERT INTO T_USER VALUES ('1','mrbird','42ee25d1e43e9f57119a00d0a39e5250',TO_DATE('2017-11-19 10:52:48','YYYY-MM-DD HH24:MI:SS'),'1');
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap input-shape guard before Subject.login (NOT an existence probe,
// to preserve the anti-enumeration message)
if (username == null || username.trim().isEmpty()
        || password == null || password.isEmpty()) {
    throw new IllegalArgumentException("用户名和密码不能为空");
}

Type guard

static boolean accountResolves(UserMapper mapper, String userName) {
    return userName != null && mapper.findByUserName(userName) != null;
}

Try / catch

try {
    SecurityUtils.getSubject().login(
        new UsernamePasswordToken(username, password));
} catch (UnknownAccountException | IncorrectCredentialsException e) {
    // generic - do NOT reveal which one failed (anti-enumeration)
    return ResponseBo.error("用户名或密码错误!");
} catch (LockedAccountException e) {
    return ResponseBo.error("账号已被锁定,请联系管理员!");
} catch (AuthenticationException e) {
    return ResponseBo.error("认证失败!");
}

Prevention

When it happens

Trigger: POSTing /login with a username that has no row in T_USER (typo, unregistered, or init.sql not loaded) makes findByUserName return null and throws before any password check. Also thrown when running against the wrong DB (init.sql is Oracle dialect: VARCHAR2/NUMBER/TO_DATE) or when UserMapper.xml's table/column names do not match the actual schema. Context: the Shiro Thymeleaf-tag module.

Common situations: Shiro Thymeleaf tags (shiro:hasPermission) render after login, but login fails because the seeded T_USER row is missing or the STATUS column was not seeded; the message is shown in the Thymeleaf login template.

Related errors


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