如何在blazor Webassembly项目的服务器端控制器中对用户进行身份验证? [英] How do I authenticate a user in serverside controller in a blazor webassembly project?

查看:98
本文介绍了如何在blazor Webassembly项目的服务器端控制器中对用户进行身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Identityserver和Facebook身份验证的出色的webassembly项目.从Webassembly调用api控制器时,使用 .AddHttpMessageHandler< BaseAddressAuthorizationMessageHandler>()设置httpclient并将useridclaimtype映射到nameidentifier后,一切工作都很好.通过 UserManager.GetUserAsync 可以使用该用户.

I have a blazor webassembly project using identityserver and facebook authentication. When calling an api controller from webassembly everything works great after setting up an httpclient with .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>() and mapping the useridclaimtype to nameidentifier. The user is available through the UserManager.GetUserAsync.

现在,我尝试添加一个纯服务器控制器,其视图希望用户能够直接从浏览器进行浏览.但是,直接浏览到服务器视图时,尽管进行了设置,但似乎没有身份验证:

Now I try to add a pure server controller with view that I want the user to be able to browse to directly from the browser. However when browsing directly to a server view there seems to be no authentication despite me setting up:

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,该用户仍然无法通过usermanager进行访问.我只会得到一个没有名称和声明的空白标识,并且如果向控制器添加 Authorize 属性,则会得到401.

I had kind of expected the middleware to do the authentication dance automatically for me with this setup. But even though I log in first and carry a .AspNetCore.Identity.Application cookie, the user is still not available through the usermanager. I only get a blank identity with no name and no claims, and if I add an Authorize attribute to the controller I get a 401.

我是否缺少一些秘密成分才能使它正常工作?我对中间件应该为我做什么有错误的期望吗?

Am I missing some secret ingredient to get this working? Do I have the wrong expectations on what the middleware should do for me?

经过一番尝试,然后比较了一个可以正常工作的标准asp.net核心项目和我的项目.看来这是杀死服务器端控制器的那一行:

After playing around a little and comparing a standard asp.net core project that works and my project. It seems that this is the line that kills the serverside controllers:

services.AddAuthentication().AddIdentityServerJwt()

如果我不添加 AddIdentityServerJwt(),则控制器表现良好,并在需要授权时重定向我,并正确登录.谁能向我解释为什么? AddIdentityServerJwt()中间件是否与返回视图的控制器不兼容?

If I don't add AddIdentityServerJwt(), the controllers behave well and redirect me when I need authorization, and log me in properly. Can anyone explain to me why that is? Is the AddIdentityServerJwt() middleware incompatible with Controllers that returns views?

在我看来,添加AddIdentityServerJwt()会增加以下要求:每个请求都需要带有承载令牌的授权标头,这是由blazor客户端httpclient提供的.但是,当浏览器直接进行呼叫时,承载令牌将丢失,并且管道也不会尝试对用户进行身份验证以获取一个.

It seems to me that adding AddIdentityServerJwt() adds the requirement that an authorization header with a bearer token is required for every request, which the blazor clientside httpclient provides. But when a browser makes a call directly, the bearer token is missing and the pipeline doesn't try to authenticate the user to get one either.

推荐答案

发生了什么

JwtBearerHandler )将是通过其

The specific mixing of the AuthorizeFilter on your controller endpoint and the usage of the AddIdentityServerJwt on your authentication builder is probably the culprit here. AddIdentityServerJwt adds the Jwt authentication scheme as the default authentication scheme indicated by the passage of the authentication scheme name in the AddAuthentication method. This means that the handler associated with this Jwt authentication scheme (JwtBearerHandler) will be the class that's emitting the 401 through its HandleChallengeAsync method. Notice there's no redirect for further action in this method which is why you don't see a redirect occurring.

为什么会这样?

由于控制器端点上的AuthorizeFilter,因此调用了JwtBearerHandler上的HandleChallengeAsync方法.执行AuthorizeFilter的方法是在过滤器初始化后立即调用).由于没有在控制器上放置的Authorization属性中指定任何策略( [Authorize] 中没有任何参数作为参数传递),因此最终使用了默认授权策略.默认策略基本上检查是否有任何身份验证方案已成功验证了您的身份(通过查看HttpContext中的身份),然后返回

The HandleChallengeAsync method on the JwtBearerHandler is invoked because of the AuthorizeFilter on your controller endpoint. The method that executes the AuthorizeFilter is the OnAuthorizationAsync method (which is invoked right after the initialization of the filter). Since there's no policy specified in the Authorization attribute put on your controller (there was nothing passed in as a parameter in [Authorize]), the default authorization policy ends up being used. The default policy basically checks if any of the authentication schemes have successfully authenticated you (by looking at the identities in the HttpContext), and return a response for a challenge if not. This challenge defaults to the challenge of the default authentication scheme which is why HandleChallengeAsync is called on the JwtBearerHandler.

您可以了解有关策略的更多信息这里,以及有关AuthorizationFilter(以及一般的过滤器)的更多信息,

You can learn more about policies here, and more about the AuthorizationFilter (and filters in general) here.

这篇关于如何在blazor Webassembly项目的服务器端控制器中对用户进行身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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