{"record":{"id":"7b9c18cbf1752562","repo":"macrozheng/mall","slug":"error-7b9c18","errorCode":null,"errorMessage":"用户名或密码错误","messagePattern":"用户名或密码错误","errorType":"exception","errorClass":"UsernameNotFoundException","httpStatus":401,"severity":"error","filePath":"mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java","lineNumber":161,"sourceCode":"        return memberDetails.getUmsMember();\n    }\n\n    @Override\n    public void updateIntegration(Long id, Integer integration) {\n        UmsMember record=new UmsMember();\n        record.setId(id);\n        record.setIntegration(integration);\n        memberMapper.updateByPrimaryKeySelective(record);\n        memberCacheService.delMember(id);\n    }\n\n    @Override\n    public UserDetails loadUserByUsername(String username) {\n        UmsMember member = getByUsername(username);\n        if(member!=null){\n            return new MemberDetails(member);\n        }\n        throw new UsernameNotFoundException(\"用户名或密码错误\");\n    }\n\n    @Override\n    public String login(String username, String password) {\n        String token = null;\n        //密码需要客户端加密后传递\n        try {\n            UserDetails userDetails = loadUserByUsername(username);\n            if(!passwordEncoder.matches(password,userDetails.getPassword())){\n                throw new BadCredentialsException(\"密码不正确\");\n            }\n            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());\n            SecurityContextHolder.getContext().setAuthentication(authentication);\n            token = jwtTokenUtil.generateToken(userDetails);\n        } catch (AuthenticationException e) {\n            LOGGER.warn(\"登录异常:{}\", e.getMessage());\n        }\n        return token;","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/macrozheng/mall/blob/0504e86b1f1b6f1b8aa6a734d37a90fb67346be7/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java#L143-L179","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (login swallows only AuthenticationException):\ntry {\n    UserDetails userDetails = loadUserByUsername(username);\n    if (!passwordEncoder.matches(password, userDetails.getPassword())) {\n        throw new BadCredentialsException(\"密码不正确\");\n    }\n    ...\n} catch (AuthenticationException e) {\n    LOGGER.warn(\"登录异常:{}\", e.getMessage());\n}\n\n// after (explicit null-check, unified message):\nUmsMember member = getByUsername(username);\nif (member == null || !passwordEncoder.matches(password, member.getPassword())) {\n    LOGGER.warn(\"登录失败, username={}\", username);\n    throw new BadCredentialsException(\"用户名或密码错误\");\n}","handlingStrategy":"try-catch","validationCode":"// Resolve the member up front and short-circuit with a generic message so the\n// portal never distinguishes 'no such member' from 'wrong password'.\nUmsMember member = memberService.getByUsername(username);\nif (member == null) {\n    return CommonResult.validateFailed(\"用户名或密码错误\");\n}","typeGuard":null,"tryCatchPattern":"// login() currently catches AuthenticationException and returns null; at the\n// controller, treat null token as a failed login with a single message.\nString token = memberService.login(username, password);\nif (token == null) {\n    return CommonResult.validateFailed(\"用户名或密码错误\");\n}","preventionTips":["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."],"tags":["spring-security","authentication","user-details-service","mall-portal","member","username-not-found"],"backgroundTag":null,"analyzedSha":"0504e86b1f1b6f1b8aa6a734d37a90fb67346be7","analyzedAt":"2026-08-13T22:19:36.553Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}