我正在开发一个blazor应用程序,在那里我将我的API项目用作Identity
提供商。一切都很好,但问题是访问令牌
由我的API发布的未经API验证。事实证明API正在期待一个
cookie标头。我仔细查看了blazor托管的应用程序,发现了
cookie与每个请求一起发送,但它的来源相同。
我的Blazor WASM项目不会自动在请求中附加此cookie
头,只是访问令牌。
有没有一种方法可以让Http处理程序在每个请求上附加这个cookie?
或者使API验证访问令牌而不是身份cookie。
这是我在API项目中的启动类
public static void AddIdentityServer(IServiceCollection services,IConfiguration configuration)
{
services.AddIdentityServer(options =>
{
options.UserInteraction.LoginUrl = "/Identity/Account/Login";
options.UserInteraction.LogoutUrl = "/Identity/Account/Logout";
}).AddProfileService<LocalProfileService>()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(option =>
{
option.Clients.Add(new Client
{
ClientId = "blazor",
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RequireClientSecret = false,
AllowedCorsOrigins = { "https://localhost:5001" },
AllowedScopes = { "openid", "profile", "email","id" },
RedirectUris = { "https://localhost:5001/authentication/login-callback" },
PostLogoutRedirectUris = { "https://localhost:5001/" },
Enabled = true,
RequireConsent = false,
});
option.IdentityResources.AddEmail();
option.IdentityResources["openid"].UserClaims.Add("name");
option.ApiResources.Single().UserClaims.Add("name");
option.IdentityResources["openid"].UserClaims.Add("role");
option.ApiResources.Single().UserClaims.Add("role");
option.IdentityResources.Add(new IdentityResource("id",new string[] {"id" }));
option.ApiResources.Single().UserClaims.Add("id");
});
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.ClientId = configuration["ExternalLoginApiKey:GoogleClientId"];
options.ClientSecret = configuration["ExternalLoginApiKey:GoogleClientSecret"];
})
.AddFacebook("Facebook", options =>
{
options.AppId = configuration["ExternalLoginApiKey:FacebookAppId"];
options.AppSecret = configuration["ExternalLoginApiKey:FacebookAppSecret"];
})
.AddIdentityServerJwt();
}
Blazor项目中的程序类
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddOidcAuthentication(options =>
{
builder.Configuration.Bind("oidc", options.ProviderOptions);
options.UserOptions.RoleClaim = "role";
}).AddAccountClaimsPrincipalFactory<CustomUserFactory>();
builder.Services.AddHttpClient<IAuthorizedRestService, AuthorizedRestService>(
client => client.BaseAddress = new Uri("https://localhost:5002/api/mart/v1/"))
.AddHttpMessageHandler(sp => sp.GetRequiredService<AuthorizationMessageHandler>()
.ConfigureHandler(authorizedUrls: new[] { "https://localhost:5002" }));
builder.Services.AddHttpClient("noauth", option => option.BaseAddress = new
Uri("https://localhost:5002/api/mart/v1/"));
builder.Services.AddScoped<IRestService, RestService>();
await builder.Build().RunAsync();
}
我找到了解决方案。
碰巧IdentityServer4已经为兼作授权服务器的API提供了JWT处理程序
.AddIdentityServerJwt();
所以我所做的是配置它
services.Configure<JwtBearerOptions>
(IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "https://localhost:5002";
options.Audience = "mart";
options.SaveToken = true;
});
然后指定要使用的身份验证方案
[Authorize(AuthenticationSchemes = IdentityServerJwtConstants.IdentityServerJwtBearerScheme)]
您也可以将其全局添加到启动类中
var authorizationPolicy = new AuthorizationPolicyBuilder(IdentityServerJwtConstants.IdentityServerJwtBearerScheme)
.RequireAuthenticatedUser().Build();
options.Filters.Add(new AuthorizeFilter(authorizationPolicy));
你可以使用这些链接阅读更多
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-3.1
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?view=aspnetcore-3.1