确认电子邮件上的 aspnet 身份无效令牌

Posted

技术标签:

【中文标题】确认电子邮件上的 aspnet 身份无效令牌【英文标题】:aspnet identity invalid token on confirmation email 【发布时间】: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。 【参考方案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

【讨论】:

以上是关于确认电子邮件上的 aspnet 身份无效令牌的主要内容,如果未能解决你的问题,请参考以下文章

MVC 5,无效的令牌

使用 ASP.NET 身份重置密码时令牌无效

ASP.NET Core Identity - 使令牌(电子邮件确认、密码重置等)在不同服务器上有效?

1 小时后身份验证令牌无效 - Firebase 中的磁盘持久性

Django - 身份验证,使用电子邮件确认注册

设计在更新时不确认电子邮件