我正在创建和配置 GraphQL 服务器和 Playground。
端点
/graphql
已经需要身份验证,但 /playground
抱怨它无法访问架构(访问被拒绝)。打开 Playground 后,GraphQL 显示 "error": "Response not successful: Received status code 401"
(未授权)。
事实上,如果我尝试直接访问
/graphql
,它也会导致我访问被拒绝。似乎不需要浏览器对用户进行身份验证。
我想配置
/playground
来验证用户身份,并使用令牌来调用 /graphql
。
这是 Web 应用程序构建:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
Settings.AppSettings = builder.Configuration;
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApi(builder.Configuration.GetRequiredSection("AzureAd"));
builder.Services.AddSingleton<AnyScalarGraphType>();
builder.Services.AddSingleton<ServiceGraphType>();
builder.Services.AddTransient<Query>();
builder.Services.AddTransient<Mutation>();
builder.Services.AddTransient<ISchema>(s => DocumentSchema.CreateSchema());
builder.Services.AddGraphQL(b => b
.AddErrorInfoProvider(opt => opt.ExposeExceptionDetails = true)
.AddUserContextBuilder(new Func<HttpContext, Dictionary<string, object?>>(httpContext => new RuntimeContext(httpContext)))
.AddSystemTextJson()
);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/health");
app.UseGraphQL("/graphql", config =>
{
config.AuthorizationRequired = true;
});
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseGraphQLPlayground(
"/playground",
new GraphQL.Server.Ui.Playground.PlaygroundOptions
{
GraphQLEndPoint = "/graphql",
RequestCredentials = GraphQL.Server.Ui.Playground.RequestCredentials.Include
}
);
}
await app.RunAsync();
这是appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Https": {
"Url": "https://+:4002"
}
}
}
}
端点 /graphql 已经需要身份验证,但是 /playground 抱怨它无法访问架构(访问被拒绝)。 打开 Playground 后,GraphQL 显示“error”:“Response 不成功:收到状态代码 401”(未授权)。
嗯,根据您的场景和描述,问题在于 Playground 如何与您的 GraphQL 端点交互。默认情况下,Playground 本身不处理身份验证,即使您的 /graphql 端点需要授权。
在调查您的共享代码时,我注意到,在您的代码中,您已将 Playground 选项的
RequestCredentials
设置为 Include
。这指示 Playground 在请求中包含任何现有的浏览器凭据。
但是,要实现此目的,您的应用程序需要有一种机制来在访问 Playground 之前设置这些凭据。这通常涉及实现登录流程,其中用户获取访问令牌并将其存储在浏览器中。
因此,成功登录后,生成访问令牌(使用 JWT 或类似的)并将其安全地存储在浏览器中,然后您就可以使用它。
您可以尝试以下修改:
app.UseWhen(context => context.Request.Path.StartsWithSegments("/playground"), appBuilder =>
{
appBuilder.UseAuthentication();
});
app.UseGraphQLPlayground(
"/playground",
new GraphQL.Server.Ui.Playground.PlaygroundOptions
{
GraphQLEndPoint = "/graphql",
RequestCredentials = GraphQL.Server.Ui.Playground.RequestCredentials.Include
}
);