加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – ASP.NET身份电子邮件确认无效令牌

发布时间:2020-12-15 20:55:30 所属栏目:百科 来源:网络整理
导读:我正在使用Asp.Net Identity.当我想使用电子邮件确认令牌确认新用户时,我系统地出现了无效令牌错误. 这是我的WebApi用户控制器: public class UsersController : ApiController{ private MyContext _db; private MyUserManager _userManager; private MyRol
我正在使用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} !rnFollow this link to set your password : rnhttps://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"));            
        }
    }
}

任何的想法 ?
非常感谢你

解决方法

我遇到了同样的问题,我设法解决了这个问题而没有实现基于机器密钥的自定义提供程序.

我有UserTokenProvider,它在UserManager类中设置,由DI按请求范围连接.因此,对于每个请求,我都在创建新的UserTokenProvider.

当我检查源代码时,我注意到默认情况下它在内部的某个地方使用DpapiDataProtectionProvider.并且使用的DpapiDataProtectionProvider的构造函数是:

public DpapiDataProtectionProvider()
  : this(Guid.NewGuid().ToString())
{
}

因此,每次创建DpapiDataProtectionProvider时,它都会生成一个用作应用程序名称的新GUID.

有两种解决方案可以解决这个问题:

>将其连接成单身人士.
>让它使用一些固定的应用程序名称.

我决定使用第二个,因为单例解决方案会再次破坏应用程序池回收等.

所以现在我的DI注册(使用Simple Injector)看起来像这样(尽管可能没有必要,仍然使用每个请求范围):

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);

希望这有助于某人.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读