基于SQLite的Razor页面登录:当前用户会话存储方案咨询
Razor页面登录会话用户信息存储方案
一、先修正你的User模型问题
你的User类构造函数存在逻辑错误:在Users.Add(new User(ID,UserName,Password,Email,LevelOfAccess,Verified));这一行,ID、UserName等字段还未被赋值,会导致添加的是默认值的空User对象;同时单个User实例不需要维护List<User>集合,完全是冗余设计。修正后的模型如下:
public class User { public int ID { get; set; } public string? UserName { get; set; } public string? Password { get; set; } public string? Email { get; set; } public int LevelOfAccess { get; set; } public int Verified { get; set; } // 业务构造函数 public User(int id, string userName, string password, string email, int levelOfAccess, int verified) { ID = id; UserName = userName; Password = password; Email = email; LevelOfAccess = levelOfAccess; Verified = verified; } // EF Core要求的无参构造函数(从数据库加载实体时需要) public User() {} }
二、跨页面共享登录用户的正确方案:ASP.NET Core Session
Razor Pages中,Session是专门为用户会话隔离存储数据的机制,完美适配你的需求——每个登录用户的信息独立存储,所有页面都能访问。
步骤1:启用Session服务
在Program.cs中配置并启用Session:
var builder = WebApplication.CreateBuilder(args); // 添加Session服务,配置超时和安全属性 builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); // 会话闲置30分钟后过期 options.Cookie.HttpOnly = true; // 禁止前端JS访问Cookie,防止XSS窃取 options.Cookie.IsEssential = true; // 标记为必要Cookie,符合隐私合规要求 }); builder.Services.AddRazorPages(); var app = builder.Build(); // 启用Session中间件(必须放在UseRouting之后、UseAuthorization之前) app.UseSession(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
步骤2:登录时将用户信息存入Session
修改你的OnPostLogin方法,必须先验证密码(你的原代码完全缺失这一步,是严重的安全漏洞),再将用户对象序列化后存入Session:
using System.Text.Json; public async Task<IActionResult> OnPostLogin() { // 1. 从数据库查询用户数据 var userData = db.ParametryUzivatele(UserNameLogin); if (userData.Rows.Count == 0) { ModelState.AddModelError("", "用户名或密码错误"); return Page(); } // 2. 验证密码(数据库必须存哈希后的密码,绝对不能存明文!) var storedPasswordHash = userData.Rows[2].ToString(); if (!VerifyPassword(PasswordLogin, storedPasswordHash)) { ModelState.AddModelError("", "用户名或密码错误"); return Page(); } // 3. 构造User对象 var currentUser = new User( Convert.ToInt32(userData.Rows[0]), userData.Rows[1].ToString(), storedPasswordHash, userData.Rows[3].ToString(), Convert.ToInt32(userData.Rows[4]), Convert.ToInt32(userData.Rows[5]) ); // 4. 序列化用户对象并存入Session var userJson = JsonSerializer.Serialize(currentUser); HttpContext.Session.SetString("CurrentUser", userJson); // 5. 登录成功跳转至主页 return RedirectToPage("/Index"); } // 密码验证方法(示例:使用ASP.NET Core官方的PasswordHasher) private bool VerifyPassword(string inputPassword, string storedHash) { var hasher = new PasswordHasher<User>(); return hasher.VerifyHashedPassword(null, storedHash, inputPassword) == PasswordVerificationResult.Success; }
步骤3:创建基类统一获取当前用户
为了避免每个页面重复编写Session读取逻辑,创建一个基类BasePageModel,让所有需要访问用户信息的页面继承它:
using System.Text.Json; using Microsoft.AspNetCore.Mvc.RazorPages; public class BasePageModel : PageModel { protected User? CurrentUser { get; set; } public override void OnPageHandlerExecuting(Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutingContext context) { var userJson = HttpContext.Session.GetString("CurrentUser"); if (!string.IsNullOrEmpty(userJson)) { CurrentUser = JsonSerializer.Deserialize<User>(userJson); } base.OnPageHandlerExecuting(context); } }
之后你的页面Model只需继承基类,就能直接使用CurrentUser:
public class IndexModel : BasePageModel { public void OnGet() { if (CurrentUser != null) { // 示例:将用户名传递给视图 ViewData["CurrentUserName"] = CurrentUser.UserName; } } }
三、关键注意事项
- 密码安全:永远不要在数据库中存储明文密码,必须使用BCrypt、PBKDF2等强哈希算法存储密码哈希值。
- Session数据精简:只存储必要的用户信息(如ID、用户名、权限等级),大量数据请在需要时从数据库查询,避免Session体积过大。
- 登录校验:在需要权限的页面,要检查
CurrentUser是否为null,若为空则强制跳转到登录页面,可在基类中统一实现。 - 序列化兼容性:确保User类无循环引用(原模型的
List<User>会导致序列化失败),所有属性可被JSON序列化。
内容的提问来源于stack exchange,提问作者Drapys
相关产品推荐
相关产品推荐

