在这个例子之后,我正在用 ASP.NET Core 2.0探索 ASP.NET 身份。一旦用户注册了自己,他们似乎就没有删除其帐户的机制。 AccountController.cs
文件不包含删除的提及。
用户应该能够删除他们的帐户,尤其是因为GDPR,但删除可能会受到限制,例如,他们的购买记录必须出于法律原因保留多年。那么实现用户自删除的最佳方法是什么?
我不是安全专家,所以我有兴趣看看我的解决方案是什么。在 ASP.NET Core 2.1中,模板将包含一个自删除选项,以符合GDPR要求。这几乎肯定会比以下更好。
我采取的策略是要求用户在删除帐户时再次输入密码。
首先在Models/ManageViewModels
文件夹中创建一个视图模型:
public class UserSelfDeleteViewModel
{
[Editable(false)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Editable(false)]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Password { get; set; }
}
该[Editable(false)]
实际上不是必需的,但它使几个月后审查代码时更容易理解。
向ManageController.cs
文件添加两个操作:
[HttpGet]
public async Task<IActionResult> UserSelfDelete()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
// Validate business rules to ensure self-deletion is allowed, though it would
// be a good idea to tell the user why their account cannot be deleted
var userSelfDelete = new UserSelfDeleteViewModel
{
Email = user.Email,
UserName = user.UserName
};
return View(userSelfDelete);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UserSelfDelete(UserSelfDeleteViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
if (await _userManager.CheckPasswordAsync(user, model.Password) == false)
{
ModelState.AddModelError("Password", "Incorrect password entered");
return View(model);
}
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out prior to account deletion.");
await _userManager.DeleteAsync(user);
return RedirectToAction(nameof(HomeController.Index), "Home");
}
现在,这需要在 Manage
文件夹中有一个视图。我想显示电子邮件地址和用户名,但将它们设为只读:
@model UserSelfDeleteViewModel
@{
ViewData["Title"] = "Delete this account";
}
<h4>@ViewData["Title"]</h4>
<div class="row">
<div class="col-md-6">
<form method="post">
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" readonly="readonly" />
</div>
<div class="form-group">
<label asp-for="UserName"></label>
<input asp-for="UserName" class="form-control" readonly="readonly" />
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" autocomplete="new-password" autofill=""/>
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Delete your account</button>
</form>
</div>
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
}
现在导航需要整理。向ManageNavPages.cs
文件添加以下行:
public static string UserSelfDelete => "UserSelfDelete";
public static string UserSelfDeleteClass(ViewContext viewContext) => PageNavClass(viewContext, UserSelfDelete);
最后在_ManageNav.cshtml
中添加一个链接,其中包含以下内容:
<li class="@ManageNavPages.UserSelfDeleteClass(ViewContext)"><a asp-action="UserSelfDelete">Delete this account</a></li>
正是由于您指出的原因,大多数网站实际上并不允许用户自行删除。即使他们有办法"删除"或"移除"您的帐户,实际发生的是删除或删除帐户的请求。这意味着要么有实时人工干预,要么有一些自动化流程以流程批准的方式处理它。
换句话说,您不会让用户从字面上对其用户记录发出 DELETE 查询。您稍后处理他们的请求,确保在实际从数据库中删除任何内容之前存档或以其他方式保留任何必要的记录。