问题:如何强制现有用户在 .Net Core 3.1 Identity 中设置 2FA?
我已经在这里看到了一些答案,但我对它们有如下问题:
如果用户尚未设置 2FA 页面,则将其重定向至登录时设置。问题是用户可以简单地跳转到不同的 url 来避免这种情况,因此实际上并没有强制执行。
执行一些过滤器,检查用户是否启用了 2FA,如果没有,则将其重定向到 MFA 设置页面。我遇到的问题是,在每次导航时,服务器都必须访问数据库来检查用户是否启用了此字段,从而对每个请求造成显着的性能影响。我知道一次数据库访问可能听起来不多,但我曾经使用过这样的应用程序,这是常态,其他事情也使用这种方法,导致一堆预操作数据库查询。除非绝对必要,否则我想避免这种行为。
我当前的想法是登录时:
检查用户凭据但不登录
userManager.CheckPasswordAsync(....)
如果凭据通过,请检查用户是否启用了 2FA。如果是,则继续执行登录流程,如果不是:
生成用户 token :
userManager.GenerateUserTokenAsync(.......)
并将其与用户名一起存储在服务器端缓存中。然后将 key 传递给缓存项目,并重定向到 2FA 设置页面,该页面不会设置 [authorize]
属性,允许未登录的用户访问它。
在 2FA 设置页面上执行任何操作之前,请使用提供的 key 检索缓存的项目并验证 token 和用户名:
userManager.VerifyUserTokenAsync(......)
如果未通过,则
返回 Unauthorized
,否则继续并从通过缓存键传递的 URL 中提供的 UserName 获取当前用户。还要转储缓存的项目和 key ,以便 URL 被狡猾的浏览器扩展抢夺时无法再次使用。继续将新的缓存 key 传递给每个 2FA 页面的新用户 token 和用户名,以在用户导航时对用户进行身份验证。
这是用户 token 的适当使用吗?这种方法足够安全吗?我担心用户未登录会带来安全问题,但我认为为了避免前面提到的在每个请求检查 2FA 时都访问数据库的问题,有必要这样做,因为尝试导航离开的方法将只需重定向到登录即可。
最佳答案
我通过 Filter Method 实现了这个
我有一个 BasePageModel
,我的所有页面都继承它
public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (!User.Identity.IsAuthenticated)
{
await next.Invoke();
return;
}
var user = await UserManager.GetUserAsync(User);
var allowedPages = new List<string>
{
"Areas_Identity_Pages_Account_ConfirmEmail",
"Areas_Identity_Pages_Account_ConfirmEmailChange",
"Areas_Identity_Pages_Account_Logout",
"Areas_Identity_Pages_Account_Manage_EnableAuthenticator",
"Areas_Identity_Pages_Account_ResetPassword",
"Pages_AllowedPageX",
"Pages_AllowedPageY",
"Pages_Privacy"
};
var page = context.ActionDescriptor.PageTypeInfo.Name;
if (!user.TwoFactorEnabled && allowedPages.All(p => p != page))
{
context.Result = RedirectToPage("/Account/Manage/EnableAuthenticator", new { area = "Identity" });
}
else
{
await next.Invoke();
}
}
然后,我更改了 Disable2fa
和 ResetAuthenticator
页面以重定向到主 2fa 页面
public IActionResult OnGet() => RedirectToPage("./TwoFactorAuthentication");
并从该页面删除了重置/禁用链接
关于asp.net-core - 如何在 .Net Core Identity 中实现 2FA?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66486574/