C# UserManager.FindAsync在密码重置后返回null
根据官方文档()和NuGet包,我在MVC5应用程序密码重置后登录时遇到问题。实体框架似乎不会在过程中刷新其上下文,只有在重新启动应用程序后,我才能使用正确的凭据登录 据我所知,我已经完成了代码示例所做的一切。只有我有更多的代码和设置(例如Unity) 这就是问题所在:C# UserManager.FindAsync在密码重置后返回null,c#,asp.net,asp.net-mvc,asp.net-identity-2,C#,Asp.net,Asp.net Mvc,Asp.net Identity 2,根据官方文档()和NuGet包,我在MVC5应用程序密码重置后登录时遇到问题。实体框架似乎不会在过程中刷新其上下文,只有在重新启动应用程序后,我才能使用正确的凭据登录 据我所知,我已经完成了代码示例所做的一切。只有我有更多的代码和设置(例如Unity) 这就是问题所在: public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { try { if (Mo
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
try
{
if (ModelState.IsValid)
{
ApplicationUser user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await this.SignInAsync(user, false);
return RedirectToLocal(returnUrl);
}
else
{
model.State = ViewModelState.Error;
model.Messages = new List<string>() { "No access buddy!" };
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
catch (Exception ex)
{
throw;
}
}
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
公共异步任务登录(LoginViewModel模型,字符串返回URL)
{
尝试
{
if(ModelState.IsValid)
{
ApplicationUser user=await UserManager.FindAsync(model.UserName,model.Password);
如果(用户!=null)
{
等待此消息。SignInAsync(用户,false);
返回重定向到本地(returnUrl);
}
其他的
{
model.State=ViewModelState.Error;
model.Messages=new List(){“No access buddy!”};
}
}
//如果我们走到这一步,有些东西失败了,重新显示形式
返回视图(模型);
}
捕获(例外情况除外)
{
投掷;
}
}
专用异步任务符号同步(应用程序用户,bool ispersist)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity identity=await UserManager.createidentitysync(用户,DefaultAuthenticationTypes.applicationcokie);
SignIn(新的AuthenticationProperties(){IsPersistent=IsPersistent},标识);
}
当我第一次登录时,这部分工作得非常好。但是,在重置密码后,无法使用新凭据登录(仍然使用旧版本)
以下是我的配置:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
#region Constructor
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
this.UserTokenProvider = new TotpSecurityStampBasedTokenProvider<ApplicationUser, string>();
}
#endregion Constructor
#region Methods
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
ApplicationUserManager manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<SecurityDbContext>()));
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
#endregion Methods
}
public class Configuration : DbConfiguration
{
public Configuration()
{
CacheTransactionHandler transactionHandler = new CacheTransactionHandler(new InMemoryCache());
this.AddInterceptor(transactionHandler);
Loaded += (sender, args) =>
{
args.ReplaceService<DbProviderServices>((s, _) => new CachingProviderServices(s, transactionHandler));
};
}
}
公共类应用程序管理员:用户管理员
{
#区域构造函数
公共应用程序服务器管理器(IUserStore存储)
:基地(商店)
{
this.UserTokenProvider=new-TotpSecurityStampBasedTokenProvider();
}
#端域构造函数
#区域方法
公共静态应用程序SerManager创建(IdentityFactoryOptions选项,IOwinContext上下文)
{
ApplicationUserManager=newApplicationUserManager(newuserStore(context.Get());
manager.UserValidator=新的UserValidator(管理器)
{
AllowOnlyAlphanumericUserNames=false,
RequireUniqueEmail=true
};
//配置密码的验证逻辑
manager.PasswordValidator=新密码验证器
{
所需长度=6,
RequiredOnletterDigit=真,
RequireDigit=true,
RequireLowercase=true,
RequireUppercase=true,
};
//配置用户锁定默认值
manager.UserLockoutEnabledByDefault=true;
manager.DefaultAccountLockoutTimeSpan=TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout=5;
//注册双因素身份验证提供商。此应用程序使用电话和电子邮件作为接收验证用户代码的步骤
//您可以编写自己的提供者并将其插入此处。
manager.RegisterWofactorProvider(“电话代码”,新电话号码提供程序)
{
MessageFormat=“您的安全代码为{0}”
});
manager.RegisterWofactorProvider(“电子邮件代码”,新的EmailTokenProvider
{
Subject=“安全代码”,
BodyFormat=“您的安全代码为{0}”
});
manager.EmailService=新的EmailService();
manager.SmsService=新的SmsService();
var dataProtectionProvider=options.dataProtectionProvider;
if(dataProtectionProvider!=null)
{
manager.UserTokenProvider=newdataprotectortokenprovider(dataProtectionProvider.Create(“ASP.NET标识”);
}
退货经理;
}
#端域法
}
这是我在启动期间配置的:
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(SecurityDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions { });
//将数据库上下文、用户管理器和登录管理器配置为每个请求使用一个实例
app.CreatePerOwinContext(SecurityDbContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);
app.CreatePerOwinContext(ApplicationSignInManager.Create);
//使应用程序能够使用cookie存储登录用户的信息
//以及使用cookie临时存储用户登录第三方登录提供商的信息
//配置登录cookie
app.UseCookieAuthentication(新的CookieAuthenticationOptions
{
AuthenticationType=DefaultAuthenticationTypes.ApplicationOkie,
LoginPath=新路径字符串(“/Account/Login”),
Provider=新CookieAuthenticationProvider
{
//允许应用程序在用户登录时验证安全戳。
//这是一种安全功能,在您更改密码或向帐户添加外部登录时使用。
OnValidateIdentity=SecurityStampValidator.OnValidateIdentity(
validateInterval:TimeSpan.FromMinutes(30),
regenerateIdentity:(管理器,用户)=>user.GenerateUserIdentityAsync(管理器))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(新的CookieAuthenticationOptions{});
最后,在几个屏幕之后,用户最终会在这里创建一个新密码:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
ApplicationUser user = await UserManager.FindByEmailAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
IdentityResult result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
else
{
AddErrors(result);
return View();
}
}
[HttpPost]
[异名]
[ValidateAntiForgeryToken]
公共异步任务ResetPassword(ResetPasswordViewModel模型)
{
如果(!ModelState.IsValid)
{
返回视图(模型);
}
ApplicationUser=await UserManager.findbyemailsync(model.Email);
if(user==null)
{
//不要透露用户不知道
public class Configuration : DbConfiguration
{
public Configuration()
{
CacheTransactionHandler transactionHandler = new CacheTransactionHandler(new InMemoryCache());
this.AddInterceptor(transactionHandler);
MyCachingPolicy cachingPolicy = new MyCachingPolicy();
Loaded += (sender, args) =>
{
args.ReplaceService<DbProviderServices>((s, _) => new CachingProviderServices(s, transactionHandler, cachingPolicy));
};
}
}
internal class MyCachingPolicy : CachingPolicy
{
#region Constructor
internal MyCachingPolicy()
{
this.NonCachableTables = new List<string>()
{
"AspNetUsers",
"Resource",
"Task",
"Appointment"
};
}
#endregion Constructor
#region Properties
private List<string> NonCachableTables { get; set; }
#endregion Properties
#region Methods
#endregion Methods
protected override bool CanBeCached(ReadOnlyCollection<EntitySetBase> affectedEntitySets, string sql, IEnumerable<KeyValuePair<string, object>> parameters)
{
return !affectedEntitySets.Select(e => e.Table ?? e.Name).Any(tableName => this.NonCachableTables.Contains(tableName));
}
protected override void GetCacheableRows(ReadOnlyCollection<EntitySetBase> affectedEntitySets, out int minCacheableRows, out int maxCacheableRows)
{
base.GetCacheableRows(affectedEntitySets, out minCacheableRows, out maxCacheableRows);
}
protected override void GetExpirationTimeout(ReadOnlyCollection<EntitySetBase> affectedEntitySets, out TimeSpan slidingExpiration, out DateTimeOffset absoluteExpiration)
{
base.GetExpirationTimeout(affectedEntitySets, out slidingExpiration, out absoluteExpiration);
}
}