Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net Core Identity电子邮件确认令牌一旦使用,应无效_C#_.net Core_Identityserver4_Asp.net Core 3.1_.net Core 3.1 - Fatal编程技术网

C# .Net Core Identity电子邮件确认令牌一旦使用,应无效

C# .Net Core Identity电子邮件确认令牌一旦使用,应无效,c#,.net-core,identityserver4,asp.net-core-3.1,.net-core-3.1,C#,.net Core,Identityserver4,Asp.net Core 3.1,.net Core 3.1,我正在使用生成令牌电子邮件确认链接,并使用验证链接。它工作得很好 问题链接应该只工作一次。如果用户使用相同的链接第二次链接应该是无效的。我调试并发现每次IdentityResult.Issuccessed都为true。我原以为第二次应该返回false,但它总是返回true 请提出解决方案。谢谢 使用.Net Core 3.1、Identity Server 4 // To Generate Token var code = await _userManager.GenerateEmailConf

我正在使用生成令牌电子邮件确认链接,并使用验证链接。它工作得很好

问题链接应该只工作一次。如果用户使用相同的链接第二次链接应该是无效的。我调试并发现每次IdentityResult.Issuccessed都为true。我原以为第二次应该返回false,但它总是返回true

请提出解决方案。谢谢

使用.Net Core 3.1、Identity Server 4

// To Generate Token
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);

// To Confirm Token
var result = await _userManager.ConfirmEmailAsync(user, code);

// Customised Token Provider
public class EmailConfirmationTokenProvider<TUser> : DataProtectorTokenProvider<TUser> where TUser : class
{
    public EmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider, 
        IOptions<EmailConfirmationTokenProviderOptions> options, ILogger<EmailConfirmationTokenProvider<TUser>> logger) 
        : base(dataProtectionProvider, options, logger)
    {
    }
}

public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{ }

// Starup.cs Code
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Tokens.EmailConfirmationTokenProvider = "email_confirmation_provider";
    options.SignIn.RequireConfirmedEmail = true;
})
    .AddDefaultTokenProviders()
    .AddTokenProvider<EmailConfirmationTokenProvider<ApplicationUser>>("email_confirmation_provider");

services.Configure<EmailConfirmationTokenProviderOptions>(options =>
{
     options.TokenLifespan = TimeSpan.FromSeconds(3600);
});
//生成令牌
var code=wait_userManager.GenerateEmailConfirmationTokenAsync(用户);
//确认代币
var result=await\u userManager.confirmemailsync(用户,代码);
//定制代币提供商
公共类EmailConfirmationTokenProvider:DataProtectorTokenProvider,其中TUser:class
{
公共电子邮件确认令牌提供程序(IDataProtectionProvider dataProtectionProvider,
IOOptions(选项,ILogger记录器)
:base(dataProtectionProvider、选项、记录器)
{
}
}
公共类EmailConfirmationTokenProviderOptions:DataProtectionTokenProviderOptions
{ }
//Starup.cs代码
服务.附加性(选项=>
{
options.Tokens.EmailConfirmationTokenProvider=“email\u confirmation\u provider”;
options.SignIn.RequireConfirmedEmail=true;
})
.AddDefaultTokenProviders()
.AddTokenProvider(“电子邮件确认提供商”);
配置(选项=>
{
options.TokenLifespan=TimeSpan.FromSeconds(3600);
});

我认为您需要将
confirmemailsync
的行为重写为这样的内容

如果令牌与指示它是有效颁发的令牌的已知用户匹配。 然后将尝试与用户管理器确认令牌。 如果确认失败,则令牌已过期,并采取适当的操作

否则,如果令牌被确认,它将从关联用户中删除,从而使该令牌的重用无效

public override async System.Threading.Tasks.Task<IdentityResult> ConfirmEmailAsync(string userId, string token) {
var user = await FindByIdAsync(userId);
if (user == null) {
    return IdentityResult.Failed("User Id Not Found");
}
var result = await base.ConfirmEmailAsync(userId, token);
if (result.Succeeded) {
    user.EmailConfirmationToken = null;
    return await UpdateAsync(user);
} else if (user.EmailConfirmationToken == token) {
    //Previously Issued Token expired
    result = IdentityResult.Failed("Expired Token");
}
return result;

请您将代码与软件包粘贴在一起,以便我检查您在做什么?@Sohan用代码更新问题。谢谢,我认为这种方法需要将EmailConfirmationToken保存在数据库中。实际上我不想保存任何令牌。如果你不保存任何东西,系统如何知道该令牌以前被使用过?@Ravi添加了另一种方法进行尝试。请检查我是否同意@Grax32。此外,标准标识实现并没有演示您尝试的方法。您确定,在我可以看到的其中一个文档上,它是公共的
UserManager.UpdateSecurityStampAsync(userId);