[英]User.Claims is empty for every page outside of Areas/Identity
授权在区域/身份之外的 Razor 页面上不起作用,无法弄清楚原因:
重现步骤:
新鲜的应用程序。 ASP.NET Core Blazor WASM 托管
创建页面: Areas/Identity/Index2.cshtml
创建页面: Areas/NewArea/NewPage.cshtml
注册并登录。
调试时访问Index2
和NewPage
并中断OnGet
方法。
Index2
:属性User.Claims
包含多个声明。NewPage
: 属性User.Claims
为空为什么授权没有“传播”到NewPage
?
当我设置@page "/Identity/NewPage"
时,它可以工作,因此它与身份区域(??)有某种关联。
编辑:
(将页面放入服务器项目的 Pages 文件夹中结果相同(无身份验证))
我关心的原因:为了快速加载,我希望我的索引页面(Index.cshtml)是剃须刀页面(不是 Blazor wasm)。 我需要在索引页面上显示登录状态。
更多研究:我在 aspnetcore repo 中发现了完全相同(未解决但已关闭)的问题。 https://github.com/dotnet/aspnetcore/issues/34080
此问题描述了与我相同的情况: 在 Blazor WebAssemby 应用程序中授权正常的 Razor 页面? 还有一个解决方案:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
})
SO上的另一个相同问题: 带有服务器端Razor页面授权问题的Blazor WebAssembly
但我仍然不明白为什么会这样。
编辑 - 解决方案
更改DefaultAuthenticateScheme
的解决方案毕竟效果不佳 - 它破坏了 api 控制器和 wasm 应用程序的授权。 这可能是由我的设置引起的 - 我实际上并没有使用服务器应用程序来“托管”Blazor。 Blazor 应用程序只是使用服务器应用程序进行身份验证和 api 的 SPA。
无论如何:我没有更改“一切”的默认架构,而是仅针对特定的 .cshtml 页面进行更改:
[AllowAnonymous]
[Authorize(AuthenticationSchemes = "Identity.Application")]
有了那个 ↑ 一切正常。 但是您必须将其粘贴到每个 .cshtml 页面中...或者-您可以在Program.cs
中对其进行配置:
//add policy which uses ApplicationScheme
services.AddAuthorization(config =>
{
config.AddPolicy("RazorPagesAuthPolicy",
policyBuilder =>
{
policyBuilder.AddAuthenticationSchemes(IdentityConstants.ApplicationScheme);
policyBuilder.RequireAssertion(context => true);//has to be here
});
}
//...
services.AddAuthentication()//keep this
.AddIdentityServerJwt();
//...
services.AddRazorPages(cfg =>
{
cfg.Conventions.AddFolderApplicationModelConvention("/", mo =>
{//add authorize and allowAnonymous filters
mo.Filters.Add(new AuthorizeFilter("RazorPagesAuthPolicy"));
mo.Filters.Add(new AllowAnonymousFilter());
}
);
}
);
我不确定这是否可行
正如我之前提到的,您可以使用 cookie 身份验证或 Jwt 身份验证来从 Server 项目访问 ClaimsPrincipal。 提出的解决方案很好,它用于配置身份系统使用的cookies中间件。 顺便说一句,它应该是:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
}).AddIdentityServerJwt();
但我还是不明白为什么会这样
你的意思是为什么上面的代码有效?
上面的代码之所以有效,是因为它配置了 cookie 中间件来对用户进行身份验证,告诉身份系统使用什么方案,以及如何质询用户。 了解这一点,您的应用程序的服务器端未经过身份验证,除非您将其配置为执行身份验证,这与您从 WebAssembly Blazor 应用程序重定向时执行的身份验证不同。 我将通过给你这个例子来试图澄清这一点:
如果您使用个人帐户创建了 Blazor Server 应用程序,然后添加了客户端 SignalR 以在您的应用程序中启用聊天系统,并且您希望使用 Authorize 属性保护您的中心对象,则 Blazor Server 应用程序的经过身份验证的用户将不会能够访问集线器上的安全端点,除非他也在集线器上进行了身份验证。 如何认证用户? 只需将应用程序 cookie 传递到集线器即可。 这与正在讨论的问题或多或少相似; 也就是说,虽然 Identity 文件夹及其内容经过了身份验证(和授权),但托管服务器应用程序却没有。
注意:很难在第一次尝试时将其内化,但请放心,建议的代码不仅有效,而且 100% 符合犹太教规。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.