gpt4 book ai didi

asp.net-mvc - asp.net 身份中的一次性登录链接

转载 作者:行者123 更新时间:2023-12-01 21:32:52 29 4
gpt4 key购买 nike

一些移动应用程序(例如 Slack)已经普及了允许用户获得一次性使用登录链接的想法(Slack 将此称为神奇登录链接)。

这个想法是,您输入电子邮件,而不必输入手 secret 码,而是请求一个神奇的登录链接,只需在手机上打开该链接即可使用该链接一次登录。

我正在 asp.net Identity 2.1 中实现此功能,但我不确定如何确保生成的链接只能使用一次。

我生成这样的 token :

var token = await _userManager.GenerateUserTokenAsync("MyLoginLink",user.Id);

此 token 将添加到用户的 URL 中。链接将您重定向到的操作方法检查该链接对于该用户是否有效,然后让您登录:

public async Task<ActionResult> LoginLink(string email, string token)
{

var user = await _userManager.FindByNameAsync(email);

// some checks ommited

//check for an expired token:
var result = await _userManager.VerifyUserTokenAsync(user.Id, "MyLoginLink", token);
if (!result)
{
// Failed
return RedirectToAction("Login");
}

await _userManager.UpdateSecurityStampAsync(user.Id);
await SignInAsync(user, true);

现在 - 如果我使用 user.UpdateSecurityStamp 更新安全标记,则会重新生成安全标记,这将使该 token 无效,并确保它无法再次使用。这样做的问题是,它还会使任何现有登录无效,因此如果用户也在桌面上登录,他们将被迫注销并再次登录。

是否有一种相对简单的方法可以在 ASP.NET 身份中创建像这样的一次性使用 token ,并且不会使所有现有登录无效?

最佳答案

您可以生成自己的 token ,因此它不依赖于 ASP.Net Identity。

您应该在 token 中添加 UserIdExpirationTime。您可以将 ExpirationTime 设置为一分钟,这样 token 就不会在很长一段时间内有效。

如果您需要确保您的 token 只是一次性的,您应该将使用过的 token 存储在内存中,并在 token 验证中检查它们,并且由于您有ExpirationTime,因此您可以清除您的 token 很快,所以它不会占用你太多的内存。

public class MagicLinkToken
{
public int UserId { get; set; }
public DateTime ExpirationTime { get; set; }
}

public class MagicLinkTokenDataFormat : ISecureDataFormat<MagicLinkToken>
{
private readonly IDataProtector dataProtector;

public MagicLinkTokenDataFormat(string name, string purpose)
{
dataProtector = new DpapiDataProtectionProvider(name).Create(purpose);
}

public string Protect(MagicLinkToken data)
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject(data);
var bytes = System.Text.Encoding.UTF8.GetBytes(json);
var protectedTokenBytes = dataProtector.Protect(bytes);
return Convert.ToBase64String(protectedTokenBytes);
}

public MagicLinkToken Unprotect(string protectedText)
{
var protectedTokenBytes = Convert.FromBase64String(protectedText);
var bytes = dataProtector.Unprotect(protectedTokenBytes);
var json = System.Text.Encoding.UTF8.GetString(bytes);
return Newtonsoft.Json.JsonConvert.DeserializeObject<MagicLinkToken>(json);
}
}

您可以创建并使用 MagicLinkTokenDataFormat 作为单例。

 MagicLinkTokenDataFormat magicLinkTokenDataFormat = new MagicLinkTokenDataFormat("APP_NAME", "PURPOSE");

生成 token

 MagicLinkToken magicLinkToken = new MagicLinkToken
{
UserId = userId,
ExpirationTime = DateTime.Now.AddMinutes(1)
};

string token = magicLinkTokenDataFormat.Protect(magicLinkToken);

验证 token

MagicLinkToken magicLinkToken = magicLinkTokenDataFormat.Unprotect(token);
if (magicLinkToken != null && magicLinkToken.ExpirationTime < DateTime.Now && !GeneratedTokens.Contains(token))
{
var user = await _userManager.FindByIdAsync(magicLinkToken.UserId);
await SignInAsync(user, true);

// add to list to ensure of one-time usage
GeneratedTokens.Add(token);
}

关于asp.net-mvc - asp.net 身份中的一次性登录链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35697149/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com