重要提示:现在有比我的答案更好的来源。按照此答案最后一部分中提供的链接进行操作。
我使用 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/