如何在 blazor webassembly 项目中对服务器端控制器中的用户进行身份验证?
Posted
技术标签:
【中文标题】如何在 blazor webassembly 项目中对服务器端控制器中的用户进行身份验证?【英文标题】:How do I authenticate a user in serverside controller in a blazor webassembly project? 【发布时间】:2020-12-19 01:12:12 【问题描述】:我有一个使用身份服务器和 facebook 身份验证的 blazor webassembly 项目。从 webassembly 调用 api 控制器时,在使用.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>()
设置 httpclient 并将 useridclaimtype 映射到 nameidentifier 后,一切正常。用户可通过UserManager.GetUserAsync
联系。
现在我尝试添加一个纯服务器控制器,其中包含我希望用户能够直接从浏览器浏览到的视图。但是,当直接浏览到服务器视图时,尽管我进行了设置,但似乎没有身份验证:
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
和
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt().AddFacebook(facebookOptions =>
facebookOptions.AppId = Configuration["id"];
facebookOptions.AppSecret = Configuration["idpwd"];
);
services.Configure<IdentityOptions>(options => options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);
我有点期待中间件通过这个设置自动为我完成身份验证。但是即使我先登录并携带 .AspNetCore.Identity.Application cookie,用户仍然无法通过用户管理器访问。我只得到一个没有名称和声明的空白身份,如果我向控制器添加 Authorize
属性,我会得到 401。
我是否遗漏了一些秘密成分来使其发挥作用?我对中间件应该为我做什么有错误的期望吗?
更新:
在玩了一会儿并比较了一个标准的 asp.net 核心项目和我的项目之后。似乎这是杀死服务器端控制器的行:
services.AddAuthentication().AddIdentityServerJwt()
如果我不添加AddIdentityServerJwt()
,控制器会表现良好并在我需要授权时重定向我,并正确登录。谁能向我解释这是为什么? AddIdentityServerJwt()
中间件是否与返回视图的控制器不兼容?
在我看来,添加 AddIdentityServerJwt() 添加了要求,即 blazor 客户端 httpclient 提供的每个请求都需要带有不记名令牌的授权标头。但是当浏览器直接进行调用时,不记名令牌丢失,并且管道也不会尝试对用户进行身份验证以获取一个。
【问题讨论】:
【参考方案1】:发生了什么
控制器端点上AuthorizeFilter 的特定混合和身份验证构建器上AddIdentityServerJwt 的使用可能是这里的罪魁祸首。 AddIdentityServerJwt adds the Jwt authentication scheme as the default authentication scheme 由 AddAuthentication 方法中的认证方案名称通过。这意味着与此 Jwt 身份验证方案 (JwtBearerHandler) 关联的处理程序将是通过其 HandleChallengeAsync 方法发出 401 的类。请注意,此方法中没有用于进一步操作的重定向,这就是您看不到重定向发生的原因。
为什么会这样?
JwtBearerHandler 上的 HandleChallengeAsync 方法由于控制器端点上的 AuthorizeFilter 而被调用。执行 AuthorizeFilter 的方法是 OnAuthorizationAsync 方法 (which is invoked right after the initialization of the filter)。由于在控制器上的 Authorization 属性中没有指定任何策略([Authorize]
中没有作为参数传入),因此最终使用默认授权策略。默认策略主要检查是否有任何身份验证方案已成功对您进行身份验证(通过查看 HttpContext 中的身份),并返回response for a challenge if not。此质询默认为默认身份验证方案的质询,这就是在 JwtBearerHandler 上调用 HandleChallengeAsync 的原因。
您可以详细了解政策 here,以及有关 AuthorizationFilter(和一般过滤器)here 的更多信息。
【讨论】:
感谢您提供的信息。我曾希望 handlechallenge 将我重定向到身份登录并为我处理所有事情,就像普通中间件在遇到 Authorize 属性时所做的那样。让它与服务器端视图一起工作似乎比它的价值更麻烦。我可能会像所有其他视图一样将角色管理 ui 和其他内容添加到 wasm 项目中。如果您知道让中间件为服务器端视图工作的任何简单方法,我将不胜感激。将此标记为答案。感谢您的帮助。 谢谢你这最终非常有帮助,我切换到在授权属性上使用 Identity.Application 来切换我想要保留服务器端的视图上的 jwt 默认策略,并且重定向的工作方式就像再次魅力,我很高兴。 :D以上是关于如何在 blazor webassembly 项目中对服务器端控制器中的用户进行身份验证?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 blazor webassembly 项目中对服务器端控制器中的用户进行身份验证?
Angular 项目中的 Blazor webassembly
检查 Blazor 应用程序是 WebAssembly 还是服务器?
如何在 Azure DevOps 上为发布服务器项目而不是客户端的 Blazor WebAssembly 托管应用程序创建构建管道?