是什么会导致"UserManager"返回错误的用户? [英] What could cause `UserManager` to return the wrong user?
问题描述
我的ASP.NET Core 2.1.0 MVC网站上发生了相当恐怖的事情.当我浏览时,突然间显示我以其他用户身份登录(当时他恰巧也在浏览该网站).
我无法确定是否有特定的用例会触发此操作,但是现在已经发生了两次.导航到其他页面仍然显示我以其他用户身份登录.似乎我还是接管了我以错误身份登录的用户的声明.
我的问题是:会发生什么?
编辑:此后,我已将userManager
和notificationService
更改为作用域",并且此问题再次发生,因此此处报告的潜在问题不能成为原因.
尝试研究这个问题,我相信罪魁祸首可能是_Layout.cshtml
中的以下调用:
@inject UserManager<ApplicationUser> userManager
@inject NotificationService notificationService
@inject CommunityService communityService
@{
ApplicationUser user = await userManager.GetUserAsync( User );
}
返回的user
用于显示用户信息并调用notificationService
和communityService
.这些还显示了与不正确(不是我)用户有关的数据.
如果重要的话,这就是在Startup.cs
中设置ApplicationDbContext
的方式:
// Add framework services.
services
.AddDbContext<ApplicationDbContext>( options => options
.UseLazyLoadingProxies()
.UseSqlServer(_configuration.GetConnectionString( "DefaultConnection" ) ) );
services
.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
我记得作用域"是建议注册实体框架以进行依赖项注入时使用的生存期.但是,NotificationService
和CommunityService
都被注册为'transient',并通过构造函数注入请求ApplicationDbContext
来访问数据.
services.AddTransient<CommunityService, CommunityService>();
services.AddTransient<NotificationService, NotificationService>();
这和它有什么关系吗?目前,我不知道这是否会有所作为.我似乎无法复制这个问题.
好消息!我是我自己造成的(我相信,请阅读下面的详细信息,以帮助我解决此问题).因此,您可以放心,除非您犯了与我相同的错误,否则不要责怪ASP MVC身份验证机制(至少,这是我目前的理解).
由于其他人可能会犯同样的错误,因此我将记录我究竟在做错什么以及如何复制.
为什么要这样做?在我的特定用例中,我想根据当前登录用户的操作向其他用户发出声明.因此,我打电话给了:
await _userManager.AddClaimAsync( userToGiveClaim, newClaim );
await _signInManager.RefreshSignInAsync( userToGiveClaim );
之所以打电话给RefreshSignInAsync
,是因为我想防止获得该声明的用户退出并让新声明生效.来自 RefreshSignInAsync
文档我觉得这应该可行:
重新生成用户的应用程序Cookie,同时保留 现有的AuthenticationProperties(如RememberMe)作为异步对象 操作.
参数 用户应刷新其登录Cookie的用户.
我仍然不太清楚为什么触发此调用时当前登录的用户会获得传递给此调用的用户的身份.那是还不是我对文档的理解方式(我将其作为错误报告),但是由于这是可复制的,所以我现在更倾向于认为我只是误解了文档.
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.
My question is: what could make this happen?
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.
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 );
}
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.
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();
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.
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.
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 );
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:
Regenerates the user's application cookie, whilst preserving the existing AuthenticationProperties like rememberMe, as an asynchronous operation.
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屋!