{"record":{"id":"857dacbcf3f8869d","repo":"paascloud/paascloud-master","slug":"uac10011028","errorCode":"UAC10011028","errorMessage":"链接已失效","messagePattern":"链接已失效","errorType":"error_code","errorClass":"UacBizException","httpStatus":null,"severity":"error","filePath":"paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/service/impl/UacUserServiceImpl.java","lineNumber":698,"sourceCode":"\n\t}\n\n\t@Override\n\tpublic void resetLoginPwd(ResetLoginPwdDto resetLoginPwdDto) {\n\t\tString confirmPwd = resetLoginPwdDto.getConfirmPwd();\n\t\tString newPassword = resetLoginPwdDto.getNewPassword();\n\t\tString resetPwdKey = resetLoginPwdDto.getResetPwdKey();\n\n\t\tPreconditions.checkArgument(!StringUtils.isEmpty(newPassword), ErrorCodeEnum.UAC10011014.msg());\n\t\tPreconditions.checkArgument(!StringUtils.isEmpty(confirmPwd), ErrorCodeEnum.UAC10011009.msg());\n\t\tPreconditions.checkArgument(!StringUtils.isEmpty(resetPwdKey), \"链接已失效\");\n\t\tPreconditions.checkArgument(newPassword.equals(confirmPwd), \"两次输入密码不一致\");\n\n\t\tString resetPwdTokenKey = RedisKeyUtil.getResetPwdTokenKey(resetPwdKey);\n\t\tUacUser uacUser = (UacUser) redisTemplate.opsForValue().get(resetPwdTokenKey);\n\n\t\tif (StringUtils.isEmpty(uacUser)) {\n\t\t\tthrow new UacBizException(ErrorCodeEnum.UAC10011028);\n\t\t}\n\n\t\tLoginAuthDto loginAuthDto = new LoginAuthDto();\n\t\tloginAuthDto.setUserName(uacUser.getUserName());\n\t\tloginAuthDto.setLoginName(uacUser.getLoginName());\n\t\tloginAuthDto.setUserId(uacUser.getId());\n\n\t\tUacUser update = new UacUser();\n\t\tString salt = generateId() + \"\";\n\t\tupdate.setLoginPwd(Md5Util.encrypt(newPassword));\n\t\tupdate.setSalt(salt);\n\t\tupdate.setId(uacUser.getId());\n\t\t// 该用户已经修改过密码\n\t\tupdate.setIsChangedPwd((Short.valueOf(\"1\")));\n\t\tupdate.setUpdateInfo(loginAuthDto);\n\n\t\tint result = uacUserMapper.updateByPrimaryKeySelective(update);\n\t\tif (result < 1) {","sourceCodeStart":680,"sourceCodeEnd":716,"githubUrl":"https://github.com/paascloud/paascloud-master/blob/781281a9503332ed3cef44ea618349d14230a127/paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/service/impl/UacUserServiceImpl.java#L680-L716","documentation":"UAC10011028 (message '链接已失效' — link has expired) is thrown by the reset-password-by-key flow when the reset token key (RedisKeyUtil.getResetPwdTokenKey(resetPwdKey)) has no value in Redis, or the value is empty. The reset link's token was never stored, was already consumed (deleted after successful reset), or expired from Redis TTL.","triggerScenarios":"Submitting resetLoginPwdByRestPwdKey(resetPwdKey, newPassword, confirmNewPassword) with a resetPwdKey whose Redis entry is missing: token expired, already used once (service deletes the key after success), Redis flushed/restarted without persistence, or a fabricated/wrong key.","commonSituations":"User clicking an emailed reset link after it expired; double-submitting the reset form (second attempt finds key deleted); Redis restart/eviction losing tokens; clocks/TTL misconfiguration making tokens short-lived; copying an incomplete token from the URL.","solutions":["Have the user request a fresh reset link and use it before expiry","Ensure the reset flow is single-use in the UI (disable after first success) to avoid confusing double submits","Check Redis connectivity and TTL configuration for the reset-token keys; enable persistence if restarts are losing tokens","Catch UacBizException code UAC10011028 and redirect the user to the 'forgot password' page to re-request a token"],"exampleFix":"// before\nuacUserService.resetLoginPwdByRestPwdKey(oldTokenFromEmail, newPwd, confirmPwd);\n// after\nString key = RedisKeyUtil.getResetPwdTokenKey(token);\nif (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {\n    uacUserService.resetLoginPwdByRestPwdKey(token, newPwd, confirmPwd);\n} else {\n    // prompt user to request a new reset link\n}","handlingStrategy":"try-catch","validationCode":"Boolean exists = redisTemplate.hasKey(RedisKeyUtil.getResetPwdTokenKey(resetPwdKey));\nif (!Boolean.TRUE.equals(exists)) { /* token expired/used: prompt new reset request */ }","typeGuard":null,"tryCatchPattern":"try { uacUserService.resetLoginPwdByRestPwdKey(key, newPwd, confirmPwd); } catch (UacBizException e) { if (\"UAC10011028\".equals(e.getCode())) { /* redirect to forgot-password to re-request token */ } }","preventionTips":["Communicate token TTL to users and expire links in the UI too","Make reset single-use in the UI to avoid double-submit confusion","Persist or back up Redis appropriately; monitor eviction of token keys"],"tags":["expired-token","redis","password-reset"],"backgroundTag":"jwt-token-expired","analyzedSha":"781281a9503332ed3cef44ea618349d14230a127","analyzedAt":"2026-09-10T10:59:02.070Z","contentChangedAt":"2026-09-10T10:59:02.070Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}