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

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

问题描述

我的ASP.NET Core 2.1.0 MVC网站上发生了相当恐怖的事情.当我浏览时,突然间显示我以其他用户身份登录(当时他恰巧也在浏览该网站).

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

我的问题是:会发生什么?


编辑:此后,我已将userManagernotificationService更改为作用域",并且此问题再次发生,因此此处报告的潜在问题不能成为原因.

尝试研究这个问题,我相信罪魁祸首可能是_Layout.cshtml中的以下调用:

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

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

如果重要的话,这就是在Startup.cs中设置ApplicationDbContext的方式:

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

我记得作用域"是建议注册实体框架以进行依赖项注入时使用的生存期.但是,NotificationServiceCommunityService都被注册为'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屋!

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