Razor项目登录页面当前用户信息持久化方案咨询
解决Razor Pages登录后用户信息持久化问题
你当前把currentUser存在LoginPage的后台类里,每次页面跳转都会重新实例化页面模型,所以数据肯定会丢。下面给你两种靠谱的解决方式,优先推荐第一种:
1. 用ASP.NET Core身份认证系统(规范且安全)
这是官方推荐的方案,自带身份验证、会话管理、安全防护,比手动存数据靠谱得多。
步骤:
(1)配置身份认证服务
在Program.cs里添加以下配置:
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Login"; // 未登录时跳转的登录页路径 options.ExpireTimeSpan = TimeSpan.FromHours(2); // 会话过期时间 }); // 别忘了添加授权服务 builder.Services.AddAuthorization(); // 中间件顺序要注意,放在UseRouting之后,UseEndpoints之前 app.UseAuthentication(); app.UseAuthorization();
(2)修改登录逻辑,生成身份票据
验证密码(记得换成BCrypt)后,创建包含用户信息的身份票据并登录:
public async Task<IActionResult> OnPostLogin() { // 先按用户名查询单个用户,不要遍历所有(性能差) var userRows = db.ParametryUzivatele(UserNameLogin).Rows; if (userRows.Count == 0) { // 用户名不存在的处理 ModelState.AddModelError("", "用户名或密码错误"); return Page(); } var dr = userRows[0]; // 替换成BCrypt验证(绝对不能明文比较密码!) if (BCrypt.Net.BCrypt.Verify(PasswordLogin, dr[2].ToString())) { // 创建Claims,只存必要的用户信息,别存密码! var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, dr[0].ToString()), new Claim(ClaimTypes.Name, dr[1].ToString()), // 按需添加其他非敏感信息,比如dr[3]、dr[4]对应的字段 }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); // 登录成功后跳转首页或其他页面 return RedirectToPage("/Index"); } else { ModelState.AddModelError("", "用户名或密码错误"); return Page(); } }
(3)在其他页面获取用户信息
任何页面的后台类里,都可以通过HttpContext.User获取当前用户的Claims:
public void OnGet() { if (User.Identity.IsAuthenticated) { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var userName = User.FindFirstValue(ClaimTypes.Name); // 按需获取其他Claims,或者根据ID从数据库查询完整用户信息 } }
2. 用Session存储(适合简单场景)
如果不想用完整的身份认证,也可以用Session暂存用户信息,但要注意Session是服务器端存储,且不要存敏感数据。
步骤:
(1)配置Session服务
在Program.cs里添加:
builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromHours(2); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); // 中间件放在UseRouting之后 app.UseSession();
(2)登录后存储用户信息到Session
修改你的OnPostLogin方法,验证成功后把用户对象序列化存到Session(注意剔除密码!):
public IActionResult OnPostLogin() { var userRows = db.ParametryUzivatele(UserNameLogin).Rows; if (userRows.Count == 0) { ModelState.AddModelError("", "用户名或密码错误"); return Page(); } var dr = userRows[0]; if (BCrypt.Net.BCrypt.Verify(PasswordLogin, dr[2].ToString())) { // 创建用户对象时不要包含密码! var currentUser = new User( dr[0].ToString(), dr[1].ToString(), // 这里跳过dr[2](密码),只存必要信息 dr[3].ToString(), dr[4].ToString(), dr[5].ToString() ); // 序列化用户对象并存入Session var userJson = System.Text.Json.JsonSerializer.Serialize(currentUser); HttpContext.Session.SetString("CurrentUser", userJson); return RedirectToPage("/Index"); } else { ModelState.AddModelError("", "用户名或密码错误"); return Page(); } }
(3)在其他页面读取Session中的用户信息
在目标页面的后台类里读取:
public User currentUser { get; set; } public void OnGet() { var userJson = HttpContext.Session.GetString("CurrentUser"); if (!string.IsNullOrEmpty(userJson)) { currentUser = System.Text.Json.JsonSerializer.Deserialize<User>(userJson); } else { // 未登录,跳转登录页 return RedirectToPage("/Login"); } }
重要提醒
- 绝对不要把用户密码存在Session、Cookie或者任何前端可访问/服务器端持久化的存储里,验证后立即丢弃密码字段。
- 密码验证必须用BCrypt这类哈希算法,禁止明文比较,你的代码里已经标注要替换,一定要尽快改。
- 遍历所有用户来匹配的方式性能很差,应该直接按用户名查询单个用户,判断是否存在再验证密码。
内容的提问来源于stack exchange,提问作者Drapys
相关产品推荐
相关产品推荐

