6

我试图自己构建这个应用程序,但在此过程中遇到了几个绊脚石。我认为最好退后一步,更深入地了解我正在尝试创建的内容。似乎没有任何关于如何制作我正在寻找的东西的文档。(除非有人能指出我可能错过的正确位置)

最终我想要的是让 Blazor(服务器端)应用程序进行 API 调用以使用应用程序中的数据,然后让 IdentityServer4 封装身份验证。我需要将 Azure 和 ASP.net Identity 作为可能的身份验证方法。

我已经尝试过并且能够创建一个也具有本地 API 的 IdentityServer4。我可以从邮递员那里打电话来获取令牌等。但是,当谈到将 Blazor(服务器端)应用程序绑定到 IdentityServer4 时,我感到很困惑。

我试图具体地问这个问题,但根本没有得到任何结果。我希望也许这个更大的视角可能会有所帮助。

odic-client.js 似乎是从 IdentityServer4 回调中获取数据的方法,但是,这似乎与 Blazor(服务器端)中的 .NET 授权不太吻合。我如何让这些一起工作。

4

2 回答 2

16

重要提示:现在有比我的答案更好的来源。按照此答案最后一部分中提供的链接进行操作。

我使用 API / IdentityServer4 / Blazor(服务器端)进行了类似的设置。我将向您展示我使用的一些代码,也许您可​​以使用它。

使用 NuGet 包 Microsoft.AspNetCore.Authentication.OpenIdConnect,我在 Startup 类的 ConfigureServices 方法中有此代码:

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("Cookies")
        .AddOpenIdConnect("oidc", options =>
        {
            options.Authority = "https://localhost:5001";

            options.ClientId = "myClient";
            options.ClientSecret = "mySecret";
            options.ResponseType = "code id_token";

            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;

            options.Scope.Add("MyApi");
            options.Scope.Add("offline_access");

            options.ClaimActions.MapJsonKey("website", "website");
        });

并在配置方法中app.UseAuthentication();

然后在 App.razor 我使用了 CascadingAuthenticationState 组件:

<CascadingAuthenticationState>
     <Router AppAssembly="typeof(Startup).Assembly" />
</CascadingAuthenticationState>

并在我的主页 Index.razor 中使用 NuGet 包 Microsoft.AspNetCore.Authorization:

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

现在,当您打开主页时,它应该显示“未通过身份验证”,但仍然没有重定向到 IdentityServer4。为此,您还必须在启动时添加 MVC,正如我从这个 stackoverflow 问题中了解到的那样:

        services.AddMvcCore(options =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            options.Filters.Add(new AuthorizeFilter(policy));
        });

现在,您应该在启动应用程序后被重定向到 IdentityServer4 以登录。就我而言,我有一个 ApiClient,它描述了我的 API 的方法。我使用 DI 注入 ApiClient 并添加访问令牌:

        services.AddHttpClient<IApiClient, ApiClient>(async (serviceProvider, client) =>
        {
            var httpContextAccessor = serviceProvider.GetService<IHttpContextAccessor>();

            var accessToken = await httpContextAccessor.HttpContext.GetTokenAsync("access_token");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

            client.BaseAddress = new Uri("http://localhost:55578");
        });

就像你说的,除了stackoverflow上的一些答案外,没有太多关于这个主题的文档。我花了很长时间来设置它,所以我希望我能在这篇文章中帮助其他人。

更新:注销过程

使用此设置注销需要绕行到 razor 页面,因为在加载 blazor 组件后无法访问 HttpContext。

在 Pages 文件夹中创建一个新的 Razor 页面,并将以下代码添加到新创建的Logout.cshtml.cs:

public class LogoutModel : PageModel
{
    public async void OnGetAsync()
    {
        await HttpContext.SignOutAsync("Cookies");
        var prop = new AuthenticationProperties()
        {
            RedirectUri = "http://localhost:62909"
        };
        await HttpContext.SignOutAsync("oidc", prop);
    }
}

在某处添加一个注销按钮,该按钮调用UriHelper.NavigateTo("/Logout")依赖于@inject IUriHelper UriHelper. 完毕!

更新:登录解决方法

前面描述的登录过程在本地工作,但在发布到测试服务器后,我遇到了问题,方法IHttpContextAccessor内部始终为 null AddHttpClient。所以我最终使用了与注销过程相同的解决方法。我让 IdentityServer 重定向到一个剃须刀页面(它总是有一个 HttpContext),将访问令牌保存在用户声明中并重定向到索引页面。在该AddHttpClient方法中,我仅从用户声明中获取令牌并将其放入身份验证标头中。

更新:未解决的问题

我仍然很难让这个设置在我们的服务器上运行。我在 AspNetCore Github 上打开了这个问题要求,但都在没有正确答案的情况下关闭了。目前,我发现一些博客很好地概述了该主题的当前状态: https ://mcguirev10.com/2019/12/15/blazor-authentication-with-openid-connect.html https:// /wellsb.com/csharp/aspnet/blazor-consume-identityserver4-protected-api/

于 2019-07-24T06:32:28.690 回答
0

试试这个
Blazor 使用 IdentityServer4 受保护的 API

于 2021-01-29T19:06:49.153 回答