ASP.NET Core MVC自定义Cookie认证下用户资料编辑功能异常及越权访问问题求助
大家好,我正在做一个ASP.NET Core MVC项目练手,已经实现了用户登录、注册和登出的基础功能,但在添加编辑用户资料功能时遇到了一系列问题,想请教一下各位:
最开始的问题是,编辑用户资料的Action里,Guid类型的Id参数总是传入空Guid({00000000-0000-0000-0000-000000000000}),而不是当前登录用户的真实Id,导致ModelState无效,而且整个过程没有抛出任何异常,我不知道该怎么正确验证用户Id来让功能正常运行。另外说明一下,我用的是自己自定义的Cookie认证,没有使用Identity框架。
后来我调试了一番,调整了登录后将用户Id传递到视图和控制器的逻辑,甚至重新写了UpdateProfile方法,但又遇到了更棘手的问题:任何登录用户都可以通过修改URL里的Guid参数,访问其他用户的资料编辑页面。比如我把URL改成localhost:44334/Users/UpdateProfile/19F17789-A52D-4752-5372-08DBA10B2W69,就能进入对应用户的编辑页面。我一开始只给UpdateProfile的一个Action加了[Authorize]特性,结果没生效,后来给两个Action都加上才限制了只有登录用户能访问,但越权访问其他用户页面的核心问题还是没解决。
下面是我相关的代码,麻烦各位帮忙看看哪里出问题了:
处理登录登出的LogUsersController
public class LogUsersController : Controller { private readonly ILogger<LogUsersController> _logger; private readonly TheAppContext _context; public static int CanUserLogout; //0/CANT, 1/CAN public static string DisplayedUsername; public static Guid DisplayedUserId; // Add this field public LogUsersController(TheAppContext context, ILogger<LogUsersController> logger) { _context = context; _logger = logger; } public ActionResult Expired() { CanUserLogout = 0; TempData["Message"] = "★ Please sign-in to gain access..."; return RedirectToAction("Login", "Logusers"); } public IActionResult Index() { return View(); } public IActionResult Login() { ViewBag.msg = TempData["Message"]; return View(); } [AllowAnonymous] [HttpPost] public async Task<IActionResult> Login(Users login) //login users { if(IsValidUser(login.Username, login.Password)) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, login.Username), new Claim(ClaimTypes.Role, "User"), }; var claimsIdentity = new ClaimsIdentity( claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties { IsPersistent = false, }; await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); _logger.LogInformation($"login.Id: {login.Id}"); DisplayedUsername = "@" + login.Username; CanUserLogout = 1; return RedirectToAction("Index", "Home"); } else { ViewBag.message = "Failed to login with @" + login.Username + ", please try again later.."; return View(); } } private bool IsValidUser(string username, string password) { var user = _context.Users.FirstOrDefault(u => u.Username == username && u.Password == password); if (user != null) { _logger.LogInformation("User found: Username = {Username}, Id = {UserId}", user.Username, user.Id); DisplayedUserId = user.Id; // Store the user's ID here return true; } _logger.LogInformation("Login failed for username: {Username}", username); return false; } [Authorize] public async Task<ActionResult> Logout() { await HttpContext.SignOutAsync( CookieAuthenticationDefaults.AuthenticationScheme); CanUserLogout = 0; return RedirectToAction("Login", "Logusers"); } }
_Layout.cshtml中的导航部分
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse"> <ul class="navbar-nav flex-grow-1"> <li class="nav-item"> <a class="nav-link text-white" asp-area="" asp-controller="Home" asp-action="Index">Home</a> </li> <li class="nav-item"> <a class="nav-link text-white" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a> </li> @if (TheApp.Controllers.LogUsersController.CanUserLogout == 1){ <li class="nav-item"> <a class="nav-link text-white" asp-area="" asp-controller="Logusers" asp-action="Logout">Logout</a> </li> <li class="nav-item"> <a class="navbar-text text-white font-italic">Hello there, @TheApp.Controllers.LogUsersController.DisplayedUsername!</a> </li> <li class="nav-item"> <a class="nav-link text-white" asp-controller="Users" asp-action="UpdateProfile" asp-route-id="@TheApp.Controllers.LogUsersController.DisplayedUserId">Profile</a> </li> } else { <li class="nav-item"> <a class="nav-link text-white" asp-area="" asp-controller="Logusers" asp-action="Login">Login</a> </li> <li class="nav-item"> <a class="nav-link text-white" asp-area="" asp-controller="Users" asp-action="Create">Register</a> </li> } </ul> </div>
处理用户注册和资料更新的UsersController
public class UsersController : Controller { private readonly TheAppContext _context; public UsersController(TheAppContext context) { _context = context; } public IActionResult Index() { return View(); } public IActionResult Create() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public IActionResult Create(Users uc) //register users { _context.Add(uc); _context.SaveChanges(); return View(uc); } [Authorize] public IActionResult UpdateProfile(Guid id) { Users user = _context.Users.SingleOrDefault(u => u.Id == id); if (user != null) { return View(user); } else { return NotFound(); } } [Authorize] [HttpPost] public IActionResult UpdateProfile(Users updatedUser) { if (ModelState.IsValid) { Users existingUser = _context.Users.FirstOrDefault(u => u.Id == updatedUser.Id); if (existingUser != null) { existingUser.Name = updatedUser.Name; existingUser.Email = updatedUser.Email; existingUser.Username = updatedUser.Username; existingUser.Password = updatedUser.Password; existingUser.ConfirmPass = updatedUser.ConfirmPass; _context.SaveChanges(); return RedirectToAction("Index", "Home"); } else { return NotFound(); } } return View(updatedUser); } }
备注:内容来源于stack exchange,提问作者Tutorial Hell Veteran
相关产品推荐
相关产品推荐

