ASP.NET Identity 2.2.1 - 发送包含代码的确认电子邮件,而不是链接

时间:2016-10-26 12:24:57

标签: c# asp.net asp.net-web-api asp.net-identity-2

我使用ASP.NET Identity 2.2.1成功构建了简单的注册系统。
我只需要API,所以我构建了一个简单的控制器,允许使用路由account/create创建帐户,当创建帐户时,用户会收到带有令牌的短信,以确认他的电话,同时我&#39 ; m生成验证电子邮件地址所需的链接,并将其发送到用户电子邮件地址。 然后用户需要从SMS输入令牌(请求account/confirm_phone)并点击他收到的电子邮件中的链接。
这两个操作都需要激活帐户,这部分工作正常。

我要求将电子邮件链接更改为电子邮件令牌,类似于用于确认电话号码的电子邮件令牌,因此用户不必点击链接就必须输入该令牌(请求account/confirm_email

方法GenerateEmailConfirmationTokenAsync会返回非常长的代码,这些代码会成为电子邮件中链接发送的一部分,我希望它能返回6位数代码。

我无法重复GeneratePhoneConfirmationTokenAsync,因为这会产生与通过短信发送相同的令牌。

我通过互联网搜索过,但我无法找到有关如何自定义GenerateEmailConfirmationTokenAsync方法生成的令牌的任何信息。

是否可以配置该令牌生成器,使其返回6(或任何可配置长度)数字代码,我可用于确认用户电子邮件地址。

我知道发送给用户的链接是更好的选择,但正如我所写,这是我得到的要求,我无法改变它。

2 个答案:

答案 0 :(得分:1)

我对此非常仔细,我担心你运气不好。

ASP.Net Identity framework(v2.2.x)有2个令牌提供者:DataProtectorTokenProviderEmailTokenProvider

DataProtectorTokenProvider为您提供了一个非常长的令牌,对于手动复制粘贴不利。但它允许设置时间跨度:DataProtectorTokenProvider.TokenLifespan。默认情况下,它设置为1天 - 请参阅该类的约束器。此提供程序生成的令牌包含当前UTC时间,userId,安全戳和附加字符串purpose,它们可以是任何内容,但在验证时,它必须与生成时相同。这通常是“电子邮件”或“电话”。然后,所有数据都由IDataProtector加密。因此,你会得到一个非常长而令人讨厌的字符串。

您可以为不同的令牌设置可变的生命周期,但在验证每个特定令牌之前,您必须围绕DataProtectorTokenProvider.TokenLifespan设置正确的值进行魔术舞蹈。

另一个选项EmailTokenProvider - 此类继承自TotpSecurityStampBasedTokenProvider。此令牌提供程序基于Rfc6238生成一次性密码(OTP)。此令牌是时间敏感的,并且在传递时间窗口后变为无效。有关详细信息,请参阅section 5.2。身份的默认时间窗口设置为3分钟。见行:

private static readonly TimeSpan _timestep = TimeSpan.FromMinutes(3);
Rfc6238AuthenticationService中的

。但是Rfc6238表示实现必须允许超过1个时间窗口。给定实现允许总共6分钟令牌寿命。如果不实施自己的Rfc6238,就没有办法改变它。

因此,Identity不会为您提供实现您的要求的方法 - 您必须自己生成令牌并将其与时间戳一起存储。也许只有其中一个 - 具有较长寿命的短令牌。默认的SMS实现已经是短暂的,并且是手动输入的简称。

答案 1 :(得分:0)

这可能不是那么容易,但是这样做的方法是编写自己的IUserTokenProvider实现。

public class CustomTokenProvider : IUserTokenProvider<ApplicationUser, string>
{
    public Task<string> GenerateAsync(string purpose, UserManager<ApplicationUser, string> manager, ApplicationUser user)
    {
        ???
    }

    public Task<bool> IsValidProviderForUserAsync(UserManager<ApplicationUser, string> manager, ApplicationUser user)
    {
        ???
    }

    public Task NotifyAsync(string token, UserManager<ApplicationUser, string> manager, ApplicationUser user)
    {
        ???
    }

    public Task<bool> ValidateAsync(string purpose, string token, UserManager<ApplicationUser, string> manager, ApplicationUser user)
    {
        ???
    }
}

然后在ApplicationUserManager的Create方法中:

manager.UserTokenProvider = new CustomTokenProvider<ApplicationUser, string>();