我有一个Webapi服务,可以生成密码重置令牌 令牌生成服务终点:
[Authorize(Users = "abcd")]
[HttpGet]
[ActionName("GenerateForgotPasswordToken")]
public async Task<IHttpActionResult> GenerateForgotPasswordToken(string key)
{
if (key == null || UserManager.FindById(key) == null)
{
return InternalServerError(new Exception("User not found"));
}
return Ok(await UserManager.GeneratePasswordResetTokenAsync(key));
}
我的应用程序UserManager:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
//var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
var manager = new ApplicationUserManager(new UserStore<IdentityUser>(new MTA()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<IdentityUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<IdentityUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
将在电子邮件中使用令牌向用户发送密码重置URL。该URL指向ASP.NET MVC视图,它是我的WebAPI项目的一部分,显然托管在IIS中的同一Web应用程序中。页面上的密码重置按钮调用我的其他服务端点,重置密码 Passowrd重置服务终点:
[HttpGet]
[AllowAnonymous]
public async Task<HttpResponseMessage> ResetPassword([FromUri]string email,[FromUri]string code,[FromUri]string password)
{
var user = await UserManager.FindByEmailAsync(email);
var result = await UserManager.ResetPasswordAsync(user.Id, code, password);
if (result.Succeeded)
{
return Request.CreateResponse();
}
return Request.CreateResponse(System.Net.HttpStatusCode.Ambiguous);
}
同样可以提一下,这两个web api端点都在同一个控制器中,在控制器中我定义了一个全局UserManger,如下所示:
private ApplicationUserManager _userManager;
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
当我使用高级REST客户端等外部工具时,我能够点击第一个端点生成令牌,然后将令牌连同电子邮件和新密码一起传递到第二个端点,并成功重置密码。但是,当我的ASP.NET MVC控制器使用第一个端点生成的相同令牌并调用passwordReset端点时,令牌无效!我已经确定没有编码/解码问题,并且第二个端点接收的令牌在两个测试中都是相同的。
我的所有WebApi和ASP控制器都在同一个项目中并托管在同一个Web应用程序中。
我认为问题可能与基于 OwinContext 的请求提交时有一个新的令牌提供程序有关,但我不明白为什么它可以通过Web浏览器调用它
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
答案 0 :(得分:1)
我在阅读完这个问题后发现了这个问题: Make ASP.NET Identity 2.0 Email confirm token work for WCF and MVC
在我的情况下,IIS配置为在运行时生成机器密钥,这就是令牌无效的原因,即使我的所有代码都作为单个应用程序运行。
以下是IIS计算机密钥配置的指南:How to Generate Machine Key using IIS