macrozheng/mall · error · UsernameNotFoundException
用户名或密码错误
Error message
用户名或密码错误
What it means
This is an inline UserDetailsService @Bean defined inside the mall-demo module's SecurityConfig, used by the demo app's authentication manager. It builds a UmsAdminExample criterion on username, runs umsAdminMapper.selectByExample, and throws UsernameNotFoundException when no row is found. Unlike the production mall-admin implementation, the returned AdminUserDetails is constructed with only the admin record and NO resourceList (no authorities are attached), so this demo path grants no granular resource permissions.
Solutions
- Confirm the demo's datasource (application.yml in mall-demo) points at a database populated with ums_admin seed rows, and that the test username exists there.
- Check umsAdminMapper is the correct MyBatis mapper and that the UmsAdminExample criterion uses the exact username column comparison (andUsernameEqualTo).
- If the demo should not authenticate against ums_admin, replace this UserDetailsService with an in-memory user (User.withUsername(...).password(...).roles(...)) for local testing.
- Provide the demo with at least one seeded admin row so selectByExample returns a non-empty list.
- Return AdminUserDetails with an explicit authorities/resource list if demo endpoints are role-protected, otherwise authorization may fail downstream.
Example fix
// before:
if (umsAdminList != null && umsAdminList.size() > 0) {
return new AdminUserDetails(umsAdminList.get(0));
}
throw new UsernameNotFoundException("用户名或密码错误");
// after (fail closed with authorities, avoid leaking the lookup miss):
if (umsAdminList == null || umsAdminList.isEmpty()) {
throw new UsernameNotFoundException("用户名或密码错误");
}
UmsAdmin admin = umsAdminList.get(0);
List<UmsResource> resources = umsResourceMapper
.selectByExample(new UmsResourceExample()); // or by admin id
return new AdminUserDetails(admin, resources); Defensive patterns
Strategy: validation
Validate before calling
// Validate the lookup result before returning UserDetails so the demo never relies
// on the exception for control flow, and so the cause is easy to diagnose.
List<UmsAdmin> rows = umsAdminMapper.selectByExample(example);
if (rows == null || rows.isEmpty()) {
LOGGER.warn("demo login: no admin row for username={}", username);
throw new UsernameNotFoundException("用户名或密码错误");
}
UmsAdmin admin = rows.get(0); Try / catch
// In the demo's protected flow, catch AuthenticationException once and redirect
// to login instead of letting it bubble as a 500.
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password));
} catch (AuthenticationException e) {
LOGGER.warn("demo auth failed for {}: {}", username, e.getMessage());
redirect("/login?error=1");
} Prevention
- Point mall-demo at a database seeded with at least one ums_admin row before exercising protected endpoints.
- If the demo is for local exploration only, replace the DB-backed UserDetailsService with an in-memory User builder so a missing table cannot break login.
- Attach authorities to AdminUserDetails in the demo too, so downstream @PreAuthorize checks behave the same as in production.
When it happens
Trigger: Any authentication against the demo app where the submitted username has no matching row in ums_admin; invoking an endpoint on mall-demo protected by the demo SecurityConfig while unauthenticated with a non-existent principal; running the demo against a database whose ums_admin table is empty.
Common situations: Running mall-demo pointed at a DB that was not loaded with the seed admin users; mistyping the demo login username; the demo's spring.datasource pointing at the wrong schema so umsAdminMapper.selectByExample returns an empty list; testing against a fresh H2/in-memory DB.
Related errors
AI-assisted analysis of macrozheng/mall@0504e86b1f (2026-08-13).
Data as JSON: /api/errors/bec631f3a397fc5d.
Report an issue: GitHub.
Appendix: source
Thrown at mall-demo/src/main/java/com/macro/mall/demo/config/SecurityConfig.java:56
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService() {
//获取登录用户信息
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UmsAdminExample example = new UmsAdminExample();
example.createCriteria().andUsernameEqualTo(username);
List<UmsAdmin> umsAdminList = umsAdminMapper.selectByExample(example);
if (umsAdminList != null && umsAdminList.size() > 0) {
return new AdminUserDetails(umsAdminList.get(0));
}
throw new UsernameNotFoundException("用户名或密码错误");
}
};
}
}
View on GitHub (pinned to 0504e86b1f)