什么可能导致 `UserManager` 返回错误的用户? [英] What could cause `UserManager` to return the wrong user?

本文介绍了什么可能导致 `UserManager` 返回错误的用户?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 ASP.NET Core 2.1.0 MVC 站点上发生了一些相当可怕的事情.在我浏览时,突然显示我以不同的用户身份登录(当时他也恰好在浏览该网站).

Something rather scary is happening on my ASP.NET Core 2.1.0 MVC site. While I was browsing, all of a sudden it shows I am logged in as a different user (who also happens to be browsing the site at that time).

我无法确定是否有特定用例触发了这种情况,但这种情况现在已经发生了两次.导航到其他页面仍然显示我以其他用户身份登录.我什至似乎接管了我错误登录的用户的声明.

I can't pinpoint whether there is a specific use case that triggers this, but this has happened twice now. Navigating to other pages still shows I am logged in as the other user. It even seems I take over the claims of the user I am incorrectly logged in as.

我的问题是:什么会导致这种情况发生?

EDIT:我已经将 userManagernotificationService 更改为 'scoped' 并且这个问题再次发生,因此这里报告的潜在问题不能成为原因.

EDIT: I have since changed userManager and notificationService to 'scoped' and this issue occurred again, thus the potential issue reported here cannot be the cause.

试图对此进行调查,我认为罪魁祸首可能是 _Layout.cshtml 中的以下调用:

Trying to look into this, I believe the culprit might be the following call in _Layout.cshtml:

@inject UserManager<ApplicationUser> userManager
@inject NotificationService notificationService
@inject CommunityService communityService
@{
    ApplicationUser user = await userManager.GetUserAsync( User );
}

返回的user用于显示用户信息并调用notificationServicecommunityService.这些还显示了与错误(不是我)用户有关的数据.

The returned user is used to show user information and do calls to notificationService and communityService. These were also showing data pertaining to the incorrect (not me) user.

如果重要,这就是 ApplicationDbContextStartup.cs 中的设置方式:

If it matters, this is how ApplicationDbContext is set up in Startup.cs:

// Add framework services.
services
    .AddDbContext<ApplicationDbContext>( options => options
        .UseLazyLoadingProxies()
        .UseSqlServer(_configuration.GetConnectionString( "DefaultConnection" ) ) );
services
    .AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

我记得'scoped'是注册实体框架进行依赖注入时推荐使用的生命周期.但是,NotificationServiceCommunityService 都注册为transient"并通过构造函数注入请求 ApplicationDbContext 来访问数据.

I recalled that 'scoped' is the recommended lifetime to use when registering Entity Framework for dependency injection. Both NotificationService and CommunityService, however, are registered as 'transient' and request ApplicationDbContext through constructor injection to access data.

services.AddTransient<CommunityService, CommunityService>();
services.AddTransient<NotificationService, NotificationService>();

这跟这有关系吗?目前,我不明白这是否会有所作为.我似乎无法复制这个问题.

Could this have anything to do with it? Currently, I do not understand whether this could make any difference. I cannot seem to replicate this issue.

推荐答案

好消息!这是我自己造成的(我相信,请阅读下面的详细信息来帮助我解决这个问题).因此,您可以放心,除非您和我犯同样的错误,否则 ASP MVC 身份验证机制不应归咎于此(至少,这是我目前的理解).

Good news! I was causing this myself (I believe, help me figure this out by reading the details below). You can thus rest assured that unless you are making the same mistake as I am, the ASP MVC authentication mechanism is not to blame here (at least, that is my current understanding).

我会记录我到底做错了什么,以及如何复制,因为其他人可能会犯同样的错误.

I will document what exactly I did wrong, and how to replicate, since others might possibly make the same mistake.

简而言之:我调用了 SignInManager.RefreshSignInAsync(TUser) 使用错误"用户(我最终登录的用户),导致我以该用户身份登录.

In short: I called SignInManager<TUser>.RefreshSignInAsync(TUser) with the 'wrong' user (the one I ended up being logged in as), causing me to be logged in as that user.

我为什么要这样做?在我的特定用例中,我想根据当前登录用户的操作向另一个用户发出声明.因此我打电话给:

Why did I do this? In my specific use case, I wanted to hand out a claim to another user based on the action of the currently logged in user. I therefore called:

await _userManager.AddClaimAsync( userToGiveClaim, newClaim );
await _signInManager.RefreshSignInAsync( userToGiveClaim );

我调用了 RefreshSignInAsync,因为我想防止获得声明的用户必须注销和登录才能使新声明生效.来自 RefreshSignInAsync 文档 我觉得这应该可行:

I called RefreshSignInAsync since I wanted to prevent the user who had been given the claim from having to log out and in for the new claim to go into effect. From the RefreshSignInAsync documentation I got the impression this should work:

重新生成用户的应用程序 cookie,同时保留现有的 AuthenticationProperties 像 rememberMe,作为异步操作.

Regenerates the user's application cookie, whilst preserving the existing AuthenticationProperties like rememberMe, as an asynchronous operation.

参数user 应刷新其登录 cookie 的用户.

Parameters user The user whose sign-in cookie should be refreshed.

我仍然不完全清楚为什么在触发此调用时当前登录的用户会获得传递给此调用的用户身份.那是仍然不是我如何理解文档(我将其作为错误报告),但由于这是可重现的,我现在更倾向于相信我只是误解了文档.

I'm still not entirely clear why the user that is currently logged in when this call is triggered gets the identity of the user passed to this call. That is still not how I understand the documentation (I filed this as a bug report), but since this is reproducible I am now more inclined to believe I simply misunderstood the documentation.

这篇关于什么可能导致 `UserManager` 返回错误的用户?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆