“令牌无效”错误,同时电子邮件确认 ASP.NET MVC

本文关键字:电子邮件 确认 ASP MVC NET 无效 令牌 令牌无效 错误 | 更新日期: 2023-09-27 18:36:16

我正在尝试将注册和登录逻辑封装到MVC中的文件中。一切正常,但我总是收到"无效令牌"。 电子邮件确认程序后出错 :(

拜托,你能帮忙吗?在寻找解决方案两天后,我变得疯狂了!

我注意到 GenerateEmailConfirmationToken 方法总是生成不同的令牌,因为它显示在日志文件中。可以吗?如果未存储令牌,则它应该始终相同,对吗?

这是我准备 ASP.NET 管理器的存储库构造函数:

    UserStore<MyUser> store = null;
    UserManager<MyUser, string> userManager = null;
    SignInManager<MyUser, string> signInManager = null;
    IAuthenticationManager authenticationManager = null;
    AbstractLogger logger = AbstractLogger.GetInstance();
public MyUserRepository(MyDbContext context) : base(context)
        {
            store = new UserStore<MyUser>(context);
            userManager = new UserManager<MyUser>(store);
            authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
            signInManager = new SignInManager<MyUser, string>(userManager, authenticationManager);
            userManager.PasswordValidator = new PasswordValidator()
            {
                RequireDigit = false,
                RequiredLength = 6,
                RequireLowercase = false,
                RequireNonLetterOrDigit = false,
                RequireUppercase = false
            };
            userManager.UserValidator = new UserValidator<MyUser>(userManager)
            {
                RequireUniqueEmail = true,
                AllowOnlyAlphanumericUserNames = true
            };
            // Configure user lockout defaults
            userManager.UserLockoutEnabledByDefault = true;
            userManager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
            userManager.MaxFailedAccessAttemptsBeforeLockout = 5;
            userManager.EmailService = new EmailService();

            var provider = new DpapiDataProtectionProvider("MyApp.org");
            userManager.UserTokenProvider = new DataProtectorTokenProvider<MyUser, string>(provider.Create("UserToken")) as IUserTokenProvider<MyUser, string>;
        }

以下是注册方法:

public void Register(MyUser user, string password)
        {
            IdentityResult result = userManager.Create(user, password);
            //For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
            //Send an email with this link
            string code = string.Empty;
            for (int i = 0; i < 10; i++)
            {
                code = userManager.GenerateEmailConfirmationToken(user.Id);
                logger.LogInfo("USER: " + user.Id + " CODE: " + code);
            }

            logger.LogInfo(
                string.Format(
                "New user {0}; {1}; {2}",
                user.Email,
                user.Id,
                code
                ));

            string callbackUrl = string.Format("http://localhost:5320/Account/ConfirmEmail?userId={0}&code={1}", user.Id, code); // }, protocol: HttpContext.Current.Request.Url.Scheme);
            userManager.SendEmail(user.Id, "Potvrzení registrace", "Please confirm your account by clicking <a href='"" + callbackUrl + "'">here</a>");
        }

这是确认方法:

    public IdentityResult ConfirmEmail(string userId, string code)
            {
                return userManager.ConfirmEmail(userId, code);
            }

以下是日志输出:

USER: 1371ccfd-e8fd-46ed-8bfb-9d51f68aca63 
CODE: AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAADOWwoIJFDEqzZ8IvsDocNQAAAAACAAAAAAAQZgAAAAEAACAAAABakUsHl8hIMJX5U5sOc4zEgxUY8ikanoiKoZyIJkttZgAAAAAOgAAAAAIAACAAAADeBcyc9fhA+UR93KdPyWf8zzbJJjAcleIzf4CHCTr3OmAAAABUmOOqZs1FhaSRTcT2gV4V7JRhXNqYuJxJzB0gbo5DDfX1d010qH7YYNe4+iBh6JwdpKXR4tmsPKpojUx3RyPTbKIU8X39CJGqeWAFXAnDZMWKH2ztSn5M5h8V1zrotZRAAAAAVbRUJlIZeKgN/FH5//NQWRBFqKc9GSq0TvMWkYgZeAOyIfTh+JAMoXA4FrYnmJswLZC44zmlZPdisKnsT81ArA==
USER: 1371ccfd-e8fd-46ed-8bfb-9d51f68aca63 
CODE: AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAADOWwoIJFDEqzZ8IvsDocNQAAAAACAAAAAAAQZgAAAAEAACAAAABwzJP5VCa/GBicSwTV4Jwu2kt3XvX3xeklIFeJPiYB5QAAAAAOgAAAAAIAACAAAACfIv9bgzQJ9gwyc6Qhn/ml5iQU2qgvO83RiQGbEK/U32AAAACTT2WpFg2BdwLZzWI033SeNK3rUckzxkFkbeFGY7LlkuOhnrjsg/IMyv5YM8sFst8her1bPFi0NDvheSdIWIzWtBQFQZi2VuHRZz3+RiLQllIT/OS/94f1h+yx93QzIGhAAAAAVvPIboy1DrTKpv1easktkMW/olF+MT10MuNlQivcx5wDUSuvzql5GM6GY87Nkm1lFzp9+n0XNWEpbFRqilBuMA==

“令牌无效”错误,同时电子邮件确认 ASP.NET MVC

使用此UserManager.GeneratePasswordResetTokenAsync方法来解决此问题。

string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
return RedirectToAction("ResetPassword", "Account", new { userId = user.Id, code = code });

请使用 Url.Action 而不是使用字符串连接创建 url。Url.Action 在最新的 MVC 版本中在后台进行编码,您可以避免编码和解码操作。

下面是您可以使用的代码片段。

string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new
    {
        userId = user.Id,
        code = code,
        returnUrl = model.ReturnUrl
    }, protocol: Request.Url.Scheme);

如果不想使用Url.Action则可以在生成 url 时使用 HttpUtility.UrlEncode(code); 对令牌进行编码

谢谢。问题实际上出在编码上。代码不应每次都相同。