{"record":{"id":"e12bd9ed90ae7eea","repo":"flipped-aurora/gin-vue-admin","slug":"error-e12bd9","errorCode":null,"errorMessage":"密码错误","messagePattern":"密码错误","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/service/system/sys_user.go","lineNumber":62,"sourceCode":"}\n\n//@author: [piexlmax](https://github.com/piexlmax)\n//@author: [SliverHorn](https://github.com/SliverHorn)\n//@function: Login\n//@description: 用户登录\n//@param: u *model.SysUser\n//@return: err error, userInter *model.SysUser\n\nfunc (userService *UserService) Login(ctx context.Context, u *system.SysUser) (userInter *system.SysUser, err error) {\n\tif nil == global.GVA_DB {\n\t\treturn nil, fmt.Errorf(\"db not init\")\n\t}\n\n\tvar user system.SysUser\n\terr = global.GVA_DB.WithContext(ctx).Where(\"username = ?\", u.Username).Preload(\"Authorities\").Preload(\"Authority\").Preload(\"Departments\").Preload(\"Positions\").Preload(\"Dept\").First(&user).Error\n\tif err == nil {\n\t\tif ok := utils.BcryptCheck(u.Password, user.Password); !ok {\n\t\t\treturn nil, errors.New(\"密码错误\")\n\t\t}\n\t\tMenuServiceApp.UserAuthorityDefaultRouter(ctx, &user)\n\t}\n\treturn &user, err\n}\n\n//@author: [piexlmax](https://github.com/piexlmax)\n//@function: ChangePassword\n//@description: 修改用户密码\n//@param: u *model.SysUser, newPassword string\n//@return: err error\n\nfunc (userService *UserService) ChangePassword(ctx context.Context, u *system.SysUser, newPassword string) (err error) {\n\tvar user system.SysUser\n\terr = global.GVA_DB.WithContext(ctx).Select(\"id, password\").Where(\"id = ?\", u.ID).First(&user).Error\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_user.go#L44-L80","documentation":"Login in UserService throws \"密码错误\" when the user record is found by username but utils.BcryptCheck fails to match the supplied password against the stored bcrypt hash. Authentication is rejected and the caller gets no user object.","triggerScenarios":"Submitting the login API with a password that doesn't match the stored hash; logging in after a password reset/change elsewhere; a client hashing or encoding the password before sending it while the server expects the plaintext to compare via bcrypt.","commonSituations":"Caps lock / keyboard layout issues; stale credentials cached in frontend storage; password containing leading/trailing whitespace; accounts created via seeding or import with unknown passwords; password field double-hashed client-side.","solutions":["Retry with the correct plaintext password (no client-side hashing).","Use the password reset / change-password flow to set a new password.","As admin, reset the user's password via the user management API.","Trim accidental whitespace from the password field before submitting."],"exampleFix":"// before\npwd := utils.BcryptHash(rawPwd) // double hashing breaks bcrypt compare\nsvc.Login(ctx, system.SysUser{Username: \"alice\", Password: pwd})\n\n// after\nsvc.Login(ctx, system.SysUser{Username: \"alice\", Password: rawPwd})","handlingStrategy":"try-catch","validationCode":"if strings.TrimSpace(password) == \"\" || strings.TrimSpace(username) == \"\" {\n    return errors.New(\"username and password are required\")\n}","typeGuard":null,"tryCatchPattern":"user, err := userService.Login(ctx, system.SysUser{Username: name, Password: pwd})\nif err != nil {\n    if strings.Contains(err.Error(), \"密码错误\") {\n        http.Error(w, \"invalid credentials\", http.StatusUnauthorized)\n        return\n    }\n    http.Error(w, err.Error(), http.StatusInternalServerError)\n}","preventionTips":["Send the plaintext password; never hash client-side","Trim whitespace from credential fields","Provide a clear reset-password path for forgotten credentials","Avoid caching stale passwords in client storage"],"tags":["authentication","password","bcrypt","go"],"backgroundTag":"invalid-credentials","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}