【问题标题】:aspnet identity invalid token on confirmation email确认电子邮件上的 aspnet 身份无效令牌
【发布时间】:2015-02-16 13:41:36
【问题描述】:

我正在尝试确认帐户,但收到“无效令牌”。错误。

这是我正在尝试的:

var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmacaoEmail", "Usuario", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);

await UserManager.SendEmailAsync(user.Id, "Ativação de Conta", user.GetEmailAtivacao(model.Nome, callbackUrl));

如果我在此代码后拨打UserManager.ConfirmEmailAsync,我可以确认帐户。但是,如果我打开它位于变量 callbackUrl 中的链接并尝试通过该操作进行确认,则会收到错误消息。

我认为这可能与 OwinContext 有关,所以我决定致电 HttpContext.GetOwinContext().GetUserManager<MyCustomUserService>,但我遇到了同样的错误。

有什么线索吗?

【问题讨论】:

  • 在我的情况下(Asp.Net Core 3.0),脚手架页面似乎引入了这个错误。请在此处查看我的answer

标签: asp.net-mvc-5 asp.net-identity-2 asp.net-identity


【解决方案1】:

传输中的代码很可能被浏览器修改。尝试对令牌执行 UrlEncode:

var code = await userManager.GenerateEmailConfirmationTokenAsync(userId);
code = System.Web.HttpUtility.UrlEncode(code);

否则浏览器会混淆令牌中可能存在的特殊符号。

【讨论】:

  • 我不知道为什么,但我已经从 POST 更改为 GET 并且它可以工作。
  • @ThiagoCustodio 意味着您从 POST 更改为 GET,是什么以及在哪里?请更具体地帮助其他人...
  • @Giox 确认令牌有问题。当我使用 POST 进行操作时,代码不起作用。因此,我更改了代码,以使用 GET 来实现该操作,并且它起作用了。对我来说这没有意义,但我可以通过这个小小的改变来解决问题。
  • @ThiagoCustodio 谢谢。是的,我也看不出有多大意义!!顺便说一句,在挣扎了几个小时后,我发现我的无效令牌是由 ApplicationUserManager.Create() 方法中 Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider(...appName) 中设置的不同应用程序名称引起的。
  • 我必须将 UrlDecode(code) 添加到 ConfirmEmail 操作中才能正常工作。
【解决方案2】:

我也遇到过同样的问题。我用下面的代码解决了这个问题。

示例:

var emailToken = _customManager.GenerateEmailConfirmationToken(userId);
emailToken = emailToken.Base64ForUrlEncode();

扩展方法 => 命名空间:System.Text,System.Web

public static class UrlEncoding
{
        public static string Base64ForUrlEncode(this string str)
        {
            byte[] encbuff = Encoding.UTF8.GetBytes(str);
            return HttpServerUtility.UrlTokenEncode(encbuff);
        }

        public static string Base64ForUrlDecode(this string str)
        {
            byte[] decbuff = HttpServerUtility.UrlTokenDecode(str);
            return Encoding.UTF8.GetString(decbuff);
        }
}

【讨论】:

    【解决方案3】:

    好吧,这浪费了我生命中的几个小时——不,是几天。在尝试了Asp.NET - Identity 2 - Invalid Token Error 中此线程中的所有其他建议后,我发现不是调用

    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
    

    在 GenerateEmailConfirmationTokenAsync-block 之前的 Register 方法中

    await SignInAsync(user, isPersistent: false);
    

    被调用,定义为

    private async Task SignInAsync(ApplicationUser user, bool isPersistent)
    {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
    }
    

    我认为这是由于使用较旧的 ASP.Net MVC 版本构建应用程序造成的。所描述的方法可以在2013年的http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity中找到。

    【讨论】:

      【解决方案4】:

      如果这些解决方案对您不起作用 - 我在 Asp.Net Core 项目中遇到了问题,因为我在 Startup.cs 中添加了以下配置:

      services.Configure<RouteOptions>(options =>
      {
        options.LowercaseUrls = true;
        options.LowercaseQueryStrings = true;
      });
      

      第二个设置导致确认码转换为小写,导致验证失败。理想情况下,我希望将查询字符串参数保持小写,并且不更改查询字符串值,但我没有找到这样做的方法,所以我只是删除了查询字符串设置:

      services.Configure<RouteOptions>(options =>
      {
        options.LowercaseUrls = true;
      });
      

      【讨论】:

        【解决方案5】:

        Serdar 的解决方案是使用 Angular 作为客户端 Web 应用程序来解决空格和 + simbols 问题的关键。

        但有时我会收到随机的“无效令牌”错误消息。在对用户的数据库进行一些查询后,我发现这些错误仅与那些用户名中有空格或破折号的用户有关。

        解决方案是配置用户管理器以允许用户名中的这些字符。意思是说我的用户数据库是从 Druppal 直接迁移到 SQL Server 的,其中许多用户避免了用户管理器中 UserValidator 的默认策略。

        您可以在本帖末尾找到如何配置 UserValidator 以允许使用非字母数字字符:

        Asp.NET - Identity 2 - Invalid Token Error

        【讨论】:

          猜你喜欢
          • 2015-08-17
          • 2015-12-13
          • 2018-03-19
          • 2015-02-15
          • 2017-10-29
          • 2015-10-08
          • 2016-12-11
          • 2020-08-07
          • 1970-01-01
          相关资源
          最近更新 更多