macrozheng/mall · error · UsernameNotFoundException
用户名或密码错误
Error message
用户名或密码错误
What it means
This is the UserDetailsService.loadUserByUsername contract implemented by the mall-portal member service (front-end/customer accounts). It calls getByUsername(username) to look up a UmsMember; when none is found it throws UsernameNotFoundException. This method is invoked both by Spring Security during portal authentication and directly by UmsMemberServiceImpl.login (line ~166), so the same throw surfaces on both interactive login and programmatic authenticate-by-token flows.
Source
Thrown at mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java:161
return memberDetails.getUmsMember();
}
@Override
public void updateIntegration(Long id, Integer integration) {
UmsMember record=new UmsMember();
record.setId(id);
record.setIntegration(integration);
memberMapper.updateByPrimaryKeySelective(record);
memberCacheService.delMember(id);
}
@Override
public UserDetails loadUserByUsername(String username) {
UmsMember member = getByUsername(username);
if(member!=null){
return new MemberDetails(member);
}
throw new UsernameNotFoundException("用户名或密码错误");
}
@Override
public String login(String username, String password) {
String token = null;
//密码需要客户端加密后传递
try {
UserDetails userDetails = loadUserByUsername(username);
if(!passwordEncoder.matches(password,userDetails.getPassword())){
throw new BadCredentialsException("密码不正确");
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
token = jwtTokenUtil.generateToken(userDetails);
} catch (AuthenticationException e) {
LOGGER.warn("登录异常:{}", e.getMessage());
}
return token;View on GitHub (pinned to 0504e86b1f)
Solutions
- Confirm the member exists: SELECT id,username,phone FROM ums_member WHERE username = ? (or by phone depending on getByUsername).
- Verify the registration flow actually persisted the member and that the client is logging in with the same identifier used at registration.
- Flush the member cache (memberCacheService.delMember / cache keys) in case a stale null is cached for the username.
- Catch UsernameNotFoundException together with BadCredentialsException in the login path and return a single generic error to avoid account enumeration.
- If login by phone or email is required, ensure getByUsername resolves the alternate identifier or extend it to do so.
Example fix
// before (login swallows only AuthenticationException):
try {
UserDetails userDetails = loadUserByUsername(username);
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadCredentialsException("密码不正确");
}
...
} catch (AuthenticationException e) {
LOGGER.warn("登录异常:{}", e.getMessage());
}
// after (explicit null-check, unified message):
UmsMember member = getByUsername(username);
if (member == null || !passwordEncoder.matches(password, member.getPassword())) {
LOGGER.warn("登录失败, username={}", username);
throw new BadCredentialsException("用户名或密码错误");
} Defensive patterns
Strategy: try-catch
Validate before calling
// Resolve the member up front and short-circuit with a generic message so the
// portal never distinguishes 'no such member' from 'wrong password'.
UmsMember member = memberService.getByUsername(username);
if (member == null) {
return CommonResult.validateFailed("用户名或密码错误");
} Try / catch
// login() currently catches AuthenticationException and returns null; at the
// controller, treat null token as a failed login with a single message.
String token = memberService.login(username, password);
if (token == null) {
return CommonResult.validateFailed("用户名或密码错误");
} Prevention
- Make registration idempotent and verify the member row is committed before returning success, so logins never hit a missing record.
- Invalidate the member cache on create/update/delete to avoid stale null lookups for recently-registered members.
- Support login by phone/email in getByUsername if that is the user-facing identifier, to cut down on 'username not found' failures.
- Unify the missing-user and wrong-password messages at the API boundary to prevent account enumeration.
When it happens
Trigger: Portal login with a username that was never registered; login attempt after the member account was deleted; the member Redis cache (memberCacheService) returning stale data for a removed member; calling login() programmatically with a token-less, non-existent username.
Common situations: Customer mistypes the registered username or uses the wrong login type (phone vs username); registration silently failed so the member row never persisted; member record deleted by an admin/cleanup job while the user's app still tries to log in; DB or MyBatis misconfiguration making getByUsername return null.
Related errors
AI-assisted analysis of macrozheng/mall@0504e86b1f (2026-08-13).
Data as JSON: /api/errors/7b9c18cbf1752562.
Report an issue: GitHub.