我正在使用最新的MVC5.2示例代码与Asp.Identity和双因素身份验证。
启用2FA后,当用户登录时,会提示输入代码(通过电话或电子邮件发送),并且他们可以选择“记住浏览器” - 这样他们就不会在该浏览器上再次询问代码。
这在VerifyCode操作中处理
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
注意 model.RememberMe
未在默认模板中使用,因此它为false。
我发现当我这样做的时候 .AspNet.TwoFactorRememberBrowser
设置已设置,会话结束时到期(因此不记得浏览器)
现在,如果我设置 isPersistent = true
, .AspNet.TwoFactorRememberBrowser
到期30天这很好,但是 .AspNet.ApplicationCookie
也会有30天到期 - 这意味着当我关闭浏览器并重新打开时,我会自动登录。
我想要它,以便它不会持续我的登录,但它将坚持我选择记住2FA代码。即用户应始终必须登录,但如果他们已经保存,则不应要求他们提供2fa代码。
有没有人看过这个,或者我错过了什么?
看起来这个代码似乎不是为了在同一个请求/响应中设置多个身份cookie,因为OWIN cookie处理程序最终共享相同的AuthenticationProperties。这是因为AuthenticationResponseGrant具有单个主体,但主体可以具有多个身份。
您可以通过在特定于2FA cookie提供程序的ResponseSignIn和ResponseSignedIn事件中更改然后还原AuthenticationProperties来解决此错误:
//Don't use this.
//app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
//Set the 2FA cookie expiration and persistence directly
//ExpireTimeSpan and SlidingExpiration should match the Asp.Net Identity cookie setting
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie,
AuthenticationMode = AuthenticationMode.Passive,
CookieName = DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie,
ExpireTimeSpan = TimeSpan.FromHours(2),
SlidingExpiration = true,
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = ctx =>
{
ctx.OwinContext.Set("auth-prop-expires", ctx.Properties.ExpiresUtc);
ctx.OwinContext.Set("auth-prop-persist", ctx.Properties.IsPersistent);
var issued = ctx.Properties.IssuedUtc ?? DateTimeOffset.UtcNow;
ctx.Properties.ExpiresUtc = issued.AddDays(14);
ctx.Properties.IsPersistent = true;
},
OnResponseSignedIn = ctx =>
{
ctx.Properties.ExpiresUtc = ctx.OwinContext.Get<DateTimeOffset?>("auth-prop-expires");
ctx.Properties.IsPersistent = ctx.OwinContext.Get<bool>("auth-prop-persist");
}
}
});
确保将相同的ExpireTimeSpan和SldingExpiration设置为主要的Asp.Net Identity cookie以保留这些设置(因为它们在AuthenticationResponseGrant中合并)。
这似乎仍然是Identity 2.2.1中的一个问题(它可以在Asp.Net Identity 3.0中修复 - 但目前已经发布,需要更高版本的.Net框架4.5)
以下工作现在似乎没问题:
使用错误的值在SignInManager.TwoFactorSignInAsync上设置cookie,因此在VerifyCode操作的成功时,我将cookie重置为持久性并给它我希望的到期日期(在这种情况下我将其设置为一年)
public async Task<ActionResult> VerifyCode(VerifyCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
} var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
switch (result)
{
case SignInStatus.Success:
// if we remember the browser, we need to adjsut the expiry date as persisted above
// Also set the expiry date for the .AspNet.ApplicationCookie
if (model.RememberBrowser)
{
var user = await UserManager.FindByIdAsync(await SignInManager.GetVerifiedUserIdAsync());
var rememberBrowserIdentity = AuthenticationManager.CreateTwoFactorRememberBrowserIdentity(user.Id);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTime.UtcNow.AddDays(365) }, rememberBrowserIdentity);
}
return RedirectToLocal(model.ReturnUrl);