确认电子邮件上的 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 身份无效令牌的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core Identity - 使令牌(电子邮件确认、密码重置等)在不同服务器上有效?