我正在使用Asp.Net Identity。当我想通过电子邮件确认令牌确认新用户时,我系统地出现了无效令牌错误。
这是我的WebApi用户控制器:
public class UsersController : ApiController
{
private MyContext _db;
private MyUserManager _userManager;
private MyRoleManager _roleManager;
public UsersController()
{
_db = new MyContext();
_userManager = new MyUserManager(new UserStore<MyUser>(_db));
_roleManager = new MyRoleManager(new RoleStore<IdentityRole>(_db));
}
//New user method
[HttpPost]
public async Task<HttpResponseMessage> Register([FromBody]PostUserModel userModel)
{
//New user code
...
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user.Id);
var message = new IdentityMessage();
message.Body = string.Format("Hi {0} !\r\nFollow this link to set your password : \r\nhttps://www.mywebsite.com/admin/users/{1}/reset?token={2}", user.UserName, user.Id, HttpUtility.UrlEncode(token));
message.Subject = "Confirm e-mail";
message.Destination = user.Email;
await _userManager.SendEmailAsync(user.Id, message.Subject, message.Body);
return Request.CreateResponse(HttpStatusCode.OK, res); }
}
要确认电子邮件,我只是这样做:
var result = await _userManager.ConfirmEmailAsync(user.Id, token);
我没有做HttpUtility.UrlDecode,因为WebApi独自完成。
我的自定义用户管理器类:
public class MyUserManager : UserManager<MyUser>
{
public MyUserManager(IUserStore<MyUser> store)
: base(store)
{
UserValidator = new UserValidator<MyUser>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
UserLockoutEnabledByDefault = false;
EmailService = new EmailService();
SmsService = new SmsService();
var dataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("MyApp");
UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<MyUser>(dataProtectionProvider.Create("UserToken"));
}
}
}
有什么想法吗? 非常感谢你
答案 0 :(得分:0)
我遇到了同样的问题,我设法解决了这个问题没有基于机器密钥实现自定义提供程序。
我已根据请求范围在DI连接的UserManager
类中设置了UserTokenProvider
。因此,对于每个请求,我都在创建新的DpapiDataProtectionProvider
。
当我检查源代码时,我注意到默认情况下它在某处使用DpapiDataProtectionProvider
。使用public DpapiDataProtectionProvider()
: this(Guid.NewGuid().ToString())
{
}
的构造函数是:
DpapiDataProtectionProvider
因此,每次创建container.Register<IUserTokenProvider<ApplicationUser, string>>(() =>
new DataProtectorTokenProvider<ApplicationUser>
(new DpapiDataProtectionProvider("MY APPLICATION NAME").Create("ASP.NET Identity"))
{
// all user tokens are only valid for 3 hours
TokenLifespan = TimeSpan.FromHours(3)
}, Lifestyle.Scoped);
时,它都会生成一个用作应用名称的新GUID。
有两种解决方案可以解决这个问题:
我决定使用第二个,因为单身人士解决方案会再次破坏应用程序池回收等。
所以现在我的DI注册(使用Simple Injector)看起来像这样(尽管可能没有必要,仍然使用每个请求范围):
.link
希望这有助于某人。