Asp.net mvc ASP.NET MVC 5 Identity 2.0设置初始用户密码

Asp.net mvc ASP.NET MVC 5 Identity 2.0设置初始用户密码,asp.net-mvc,Asp.net Mvc,我已经建立了一个MVC5网站。添加用户会生成并发送带有确认令牌的电子邮件。当用户单击电子邮件链接时,网站会做出响应,要求用户设置初始密码 当用户尝试设置初始密码时,用户尚未登录,因此user.Identity.GetUserId()为null。如何将用户ID从确认链接传递到调用SetPassword() AccountController.cs //获取:/Account/ConfirmEmail [异名] 公共异步任务确认邮件(字符串用户ID、字符串代码) { if(userId==null

我已经建立了一个MVC5网站。添加用户会生成并发送带有确认令牌的电子邮件。当用户单击电子邮件链接时,网站会做出响应,要求用户设置初始密码

当用户尝试设置初始密码时,用户尚未登录,因此
user.Identity.GetUserId()
null
。如何将用户ID从确认链接传递到调用
SetPassword()

AccountController.cs
//获取:/Account/ConfirmEmail
[异名]
公共异步任务确认邮件(字符串用户ID、字符串代码)
{
if(userId==null | | code==null)
返回视图(“错误”);
var result=await UserManager.confirmemailsync(userId,code);
if(result.successed)
使用(var s=new UserStore())
{
var u=s.FindByIdAsync(userId).Result;
等待s.SetEmailConfirmedAsync(u,true);
return视图(“ConfirmEmail”,new{Id=userId});//这似乎没有使Id可用。
}
其他的
返回视图(“错误”);
}
ConfirmEmail.cshtml
@{
ViewBag.Title=“确认电子邮件”;
}
@ViewBag.Title。

感谢您确认您的电子邮件。
请@Html.ActionLink(“单击此处创建密码。”,
“设置密码”、“管理”,
routeValues:null,//我已尝试传递新的{Id=Model.Id},但在运行时Id不可用。
htmlAttributes:new{id=“loginLink”})

ManageController.cs
//POST:/Manage/SetPassword
[HttpPost]
[异名]
[ValidateAntiForgeryToken]
公共异步任务SetPassword(SetPasswordViewModel模型)
{
if(ModelState.IsValid)
{
var result=await UserManager.AddPasswordAsync(User.Identity.GetUserId(),model.NewPassword);
if(result.successed)
{
var user=await UserManager.FindByIdAsync(user.Identity.GetUserId());
如果(用户!=null)
{
等待SignInManager.SignInAsync(用户,isPersistent:false,rememberBrowser:false);
}
返回RedirectToAction(“Index”,new{Message=ManageMessageId.SetPasswordSuccess});
}
加法器(结果);
}
//如果我们走到这一步,有些东西失败了,重新显示形式
返回视图(模型);
}

一个简单的修复方法是向SetPassword方法添加一个参数:

public async Task<ActionResult> SetPassword(SetPasswordViewModel model, Guid userIdentifier)
当用户单击链接时,您现在应该用发送电子邮件的用户的ID填写userIdentifier

这不是超级安全的,因为他们可以传递任何Guid(如果他们能够确定要发送哪个Guid的话)

您可能希望通过ID(而不是userIdentifier)跟踪PasswordRequest对象,该ID可能会使电子邮件过期,在这种情况下,他们需要请求一个新的PasswordRequest对象。这样,一旦使用了PasswordRequest记录,就可以将其删除以防止重复使用


注意:PasswordRequest只是一个虚构的名称。

您在第一次创建用户时收集了密码,因此您的
UserManager.CreateAsync()
不需要id。创建新行(并生成id)后,将在注册操作中发送确认电子邮件令牌


SetPassword()
操作用于现有且经过身份验证的用户更改密码。您不应将其标记为
[AllowAnonymous]

您可以使用查询字符串,在确认令牌中,您可以加密用户名或用户ID,当您到达重置页面时,将其解密,并将
标识设置为任何人

编辑:除此之外,您还可以在数据库
InitialSetup
中创建一个新表,其中包含
user
encryptedd(guid)
Initial


当有人单击电子邮件链接时,他们需要输入
用户名
,以及新密码。此时,您将检查输入用户名是否与
encryptedd(guid)

站点管理员将创建的用户帐户相同。管理员不想处理密码。用户是否没有惯用的方法在通过电子邮件确认帐户后创建自己的密码?设计一个系统来生成首次密码。然后让管理员用生成的密码注册新用户,并将帐户标记为未验证。用户第一次登录时,他们将被迫更新密码。现在,通过您的
SetPassword()
操作设置,恶意用户可以尝试任何id并更新密码。我感谢您的帮助。我想知道我是否试图不恰当地使用内置功能。
Model.ID
在运行时不可用。我遗漏了什么吗?使用任何你想要传递的跟踪令牌来稍后找到用户。哈哈!这是我第一次尝试的。不幸的是,我没弄好。看完你的回复后,我又试了一次,结果成功了。然而,这种不安全的警告让我重新思考了这种方法。所以我还不确定马克的回答是什么。
public async Task<ActionResult> SetPassword(SetPasswordViewModel model, Guid userIdentifier)
   Please @Html.ActionLink("click here to create a password.",
        "SetPassword", "Manage",
        routeValues: null, // I've tried passing new { Id = Model.Id }, but Id isn't available at run-time.
        htmlAttributes: new { id = "loginLink", userIdentifier = Model.ID })