将Blazor Server应用程序项目从Dotnet 5迁移到Dotnet 6之后,我遇到了身份验证的奇怪问题。
该应用程序使用本地用户名和密码进行身份验证。
在Configureservices()中,我们现在已经
services.AddDefaultIdentity<IdentityUser>
(options =>
{
options.SignIn.RequireConfirmedAccount = true;
// attempt to force name claim to "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
options.ClaimsIdentity.UserNameClaimType = System.Security.Claims.ClaimTypes.Name;
})
.AddRoles<IdentityRole>()
.AddUserManager<UserManager<IdentityUser>>()
.AddRoleManager<AspNetRoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Dev环境中的.NET 5以及Azure App Services(Windows / iis)中都可以正常工作
。
- 在 (使用“项目”启动):一切都像以前一样工作(包括身份验证)
- 产品环境(Azure App Service):损坏了身份验证。当某人登录时,“ Identity.isauthenticatienated”是正确的,但是“ Identity.name”为null。
我将问题追溯到以下:
2022-05-17 12:46:54.190 +12:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier = 7f041757-3aad-4221-971a-729598c1d81e
2022-05-17 12:46:54.190 +12:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name = superadmin@local
2022-05-17 12:46:54.190 +12:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress = [email protected]
2022-05-17 12:46:54.190 +12:00 [INF] Claim AspNet.Identity.SecurityStamp = OJLEYFWG4JE4ND5NRPTRT4JVCVEE2ANR
2022-05-17 12:46:54.191 +12:00 [INF] Claim http://schemas.microsoft.com/ws/2008/06/identity/claims/role = SuperAdmin
2022-05-17 12:46:54.191 +12:00 [INF] Claim amr = pwd
但是在prod(Azure App Services)中,索赔如下如下,
2022-05-17 01:16:12.467 +00:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier = 7f041757-3aad-4221-971a-729598c1d81e
2022-05-17 01:16:12.468 +00:00 [INF] **Claim name = superadmin@local**
2022-05-17 01:16:12.471 +00:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress = [email protected]
2022-05-17 01:16:12.472 +00:00 [INF] Claim AspNet.Identity.SecurityStamp = OJLEYFWG4JE4ND5NRPTRT4JVCVEE2ANR
2022-05-17 01:16:12.473 +00:00 [INF] Claim http://schemas.microsoft.com/ws/2008/06/identity/claims/role = SuperAdmin
2022-05-17 01:16:12.475 +00:00 [INF] Claim http://schemas.microsoft.com/claims/authnmethodsreferences = pwd
2022-05-17 01:16:12.477 +00:00 [INF] Claim nameid = 7f041757-3aad-4221-971a-729598c1d81e
2022-05-17 01:16:12.478 +00:00 [INF] Claim email = [email protected]
2022-05-17 01:16:12.480 +00:00 [INF] Claim role = SuperAdmin
2022-05-17 01:16:12.481 +00:00 [INF] Claim amr = pwd
索赔 http://schemas.xmlsoap.org/ws/ws/2005/ 05/Identity/apports/name
是缺少。相反,我们可以看到称为 name
保留用户名值的索赔。
我试图强迫该应用使用正确的索赔名称,
options.ClaimsIdentity.UserNameClaimType = System.Security.Claims.ClaimTypes.Name;
但这无效。它仍然使用错误的名称。
可以肯定的是,这是某个地方缺少的简单配置 - 如果有人可以指出?
更新1
我更新了代码,如下所示
if (IsProduction)
{
options.ClaimsIdentity.UserNameClaimType = 'name';
}
,并允许用户登录。Identity.isauthenticated== true and Identity.name!= null。
哇! ... 但为什么??
另外,以下在ASPNET 6上的DEV中的作品:
[Inject]
IHttpContextAccessor HCA { get; set; }
if (HCA?.HttpContext?.User?.Claims?.Any() == true)
{
foreach (var claim in HCA.HttpContext.User.Claims)
{
Logger.Log("HCA Type = {t} Value = {v}", claim.Type, claim.Value);
}
}
但是在prod,在Azure App Services上,检查 HCA?.httpContext?.user?.claims?.claims?.any()== true
失败。这意味着httpcontext中没有索赔。那怎么可能???
另外,
我将ASP.NET Core 6.0(X64)扩展安装到Azure Web应用程序中。它安装正常,但对身份验证错误没有影响。
更新2
我找到了问题的根源,但尚未找到解决方案。
事实证明,Azure Signal R正在弄乱事情。
在startup.cs中,我有此代码:
if (IsProduction)
{
services.AddSignalR().AddAzureSignalR(options =>
{
options.ServerStickyMode = Microsoft.Azure.SignalR.ServerStickyMode.Required;
});
}
如果我删除此代码,则索赔恢复正常,含义:
- 名称索赔现在
http://schemas.xmlsoap.org/ws/ws/2005/2005/05/inidentity/claims /name
- httpcontext再次工作,
但是我当然会失去Azure Signalr,这是不好的。
甚至奇怪的是:我使用“本地身份验证”模板创建了一个新的Aspnet 6 Blazor Server应用程序项目,并将其部署到Azure App Services。现在,索赔行为略有不同:
- 名称索赔是正确的
http://schemas.xmlsoap.org/ws/2005/05/sidentity/claims/name
- 一个称为
simelor_name的新声明/code>被添加到索赔的
- httpcontext损坏中。
州 |
名称索赔 |
httpcontext |
升级的ASPNET 5项目;没有Azure Signal r |
OK |
升级 |
ASPNET 5项目; 带有 azure信号r |
破裂的 |
新鲜 |
Aspnet 6项目; 使用 azure信号r |
工作 |
破裂 |
,因此,结果是:Azure Signalr肯定会为我搞砸身份验证。但为什么?我该如何解决?
更新3
因此,事实证明,
R。
Fresh Net 6项目正在使用System.IdentityModel.tokens.jwt 6.8.0.11012 ( 最新
System.InderityModel.tokens.jwt 6.18,现在对我升级的Net5项目进行身份验证。
要了解更多信息,请参见 github问题
ps。对Azure Signalr团队表示敬意,指向我指向正确的方向
After migrating a Blazor Server App project from dotnet 5 to dotnet 6, I'm encountering a weird problem with authentication.
The app is using local username and password for authentication.
In ConfigureServices(), we have
services.AddDefaultIdentity<IdentityUser>
(options =>
{
options.SignIn.RequireConfirmedAccount = true;
// attempt to force name claim to "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
options.ClaimsIdentity.UserNameClaimType = System.Security.Claims.ClaimTypes.Name;
})
.AddRoles<IdentityRole>()
.AddUserManager<UserManager<IdentityUser>>()
.AddRoleManager<AspNetRoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Now, this has been working fine in .net 5, both in the dev environment, and also in Azure App Services (windows / iis )
After upgrading to .net 6, the following is observed:
- Dev environment (launched using "Project" ): Everything works as before (including authentication)
- Prod environment (Azure App Service) : Authentication is broken. When someone logs in, 'Identity.IsAuthenticated' is true, but 'Identity.Name' is null.
I traced the problem to the following:
- in Dev, the claims are as follows:
2022-05-17 12:46:54.190 +12:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier = 7f041757-3aad-4221-971a-729598c1d81e
2022-05-17 12:46:54.190 +12:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name = superadmin@local
2022-05-17 12:46:54.190 +12:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress = [email protected]
2022-05-17 12:46:54.190 +12:00 [INF] Claim AspNet.Identity.SecurityStamp = OJLEYFWG4JE4ND5NRPTRT4JVCVEE2ANR
2022-05-17 12:46:54.191 +12:00 [INF] Claim http://schemas.microsoft.com/ws/2008/06/identity/claims/role = SuperAdmin
2022-05-17 12:46:54.191 +12:00 [INF] Claim amr = pwd
But in Prod (Azure App services), the claims are as follows
2022-05-17 01:16:12.467 +00:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier = 7f041757-3aad-4221-971a-729598c1d81e
2022-05-17 01:16:12.468 +00:00 [INF] **Claim name = superadmin@local**
2022-05-17 01:16:12.471 +00:00 [INF] Claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress = [email protected]
2022-05-17 01:16:12.472 +00:00 [INF] Claim AspNet.Identity.SecurityStamp = OJLEYFWG4JE4ND5NRPTRT4JVCVEE2ANR
2022-05-17 01:16:12.473 +00:00 [INF] Claim http://schemas.microsoft.com/ws/2008/06/identity/claims/role = SuperAdmin
2022-05-17 01:16:12.475 +00:00 [INF] Claim http://schemas.microsoft.com/claims/authnmethodsreferences = pwd
2022-05-17 01:16:12.477 +00:00 [INF] Claim nameid = 7f041757-3aad-4221-971a-729598c1d81e
2022-05-17 01:16:12.478 +00:00 [INF] Claim email = [email protected]
2022-05-17 01:16:12.480 +00:00 [INF] Claim role = SuperAdmin
2022-05-17 01:16:12.481 +00:00 [INF] Claim amr = pwd
The claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
is MISSING. Instead we can see the claim called name
holding the username value.
I tried to force the app to use the correct claim name
options.ClaimsIdentity.UserNameClaimType = System.Security.Claims.ClaimTypes.Name;
but that didn't work. Its still using the wrong name.
Pretty sure it is a simple configuration missing somewhere - if someone can point it out?
UPDATE 1
I updated the code as follows
if (IsProduction)
{
options.ClaimsIdentity.UserNameClaimType = 'name';
}
This actually worked and allowed the user to log in. Identity.IsAuthenticated == true and Identity.Name != null.
Hooray! ... But.. why??
Also, the following works in DEV on ASPNET 6 :
[Inject]
IHttpContextAccessor HCA { get; set; }
if (HCA?.HttpContext?.User?.Claims?.Any() == true)
{
foreach (var claim in HCA.HttpContext.User.Claims)
{
Logger.Log("HCA Type = {t} Value = {v}", claim.Type, claim.Value);
}
}
But in Prod, on Azure App Services, the check HCA?.HttpContext?.User?.Claims?.Any() == true
FAILS. Meaning that there are no claims in HttpContext. How is that possible???
ALSO
I installed the ASP.NET core 6.0 (x64) Extension to Azure Web App. It installed fine, but did not make a difference to authentication error.
UPDATE 2
I found the source of the problem, but not the solution, yet.
It turns out that Azure Signal R is messing things up.
In Startup.cs I have this code:
if (IsProduction)
{
services.AddSignalR().AddAzureSignalR(options =>
{
options.ServerStickyMode = Microsoft.Azure.SignalR.ServerStickyMode.Required;
});
}
If I remove this, then the claims go back to normal, meaning:
- Name claim is now
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
- HttpContext works again
But of course I lose Azure SignalR which is no good.
What is even weirder is this: I created a fresh ASPNET 6 Blazor Server App project using the "Local Authentication" template, and deployed that to Azure App Services. Now, the claims behaviour is slightly different:
- Name claim is correct
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
- A new claim called
unique_name
is added to the ClaimsPrincipal
- HttpContext is broken.
State |
Name Claim |
HttpContext |
Upgraded ASPNET 5 Project; No Azure Signal R |
OK |
Working |
Upgraded ASPNET 5 Project; with Azure Signal R |
Broken |
Broken |
Fresh ASPNET 6 Project; with Azure Signal R |
Working |
Broken |
So, the upshot is: Azure SignalR is definitely screwing up authentication for me. But why? And how do I fix it?
Update 3
So, it turns out that the version of System.IdentityModel.Tokens.Jwt matters when using Azure Signal R.
In the experiments above,
- the upgraded NET5>NET6 project was using System.IdentityModel.Tokens.Jwt 6.10.0.20330 (name claim wrong, unique_name claim missing)
- the Fresh NET 6 project was using System.IdentityModel.Tokens.Jwt 6.8.0.11012 (a lower version - strangely enough) (name claim OK, unique_name claim exists)
To fix my problem, I simply upgraded to the latest
System.IdentityModel.Tokens.Jwt 6.18 and now authentication for my upgraded NET5 project works again.
To understand more, see the github issue
PS. Kudos to the Azure SignalR team for pointing me in the right direction
发布评论
评论(1)
解决方法: -
升级.net5到.net6 project使用
system.IndestityModel.tokens.tokens.jwt 6.10.0.20330
(name Spaim sopport错误,simelion_name声称失踪)。要解决此升级到 ,然后对您升级的
.net5
项目进行身份验证。PS: - AS
版本6.10
与Azure SignalR不正常工作。有关更多信息,请参阅此信息 Microsoft文档 github问题
Workaround:-
When upgrading .NET5 to .NET6 project was using
System.IdentityModel.Tokens.Jwt 6.10.0.20330
(name claim wrong, unique_name claim missing).To resolve this upgrade to the latest version of
System.IdentityModel.Tokens.Jwt 6.18
and then authentication for your upgraded.NET5
project will works again.P.S:- As
version 6.10
does not work properly with Azure Signal R.For more information please refer this MICROSOFT DOCUMENTATION & GitHub issue