5

我正在使用GraphQL for .NET包的 graphql。但我不明白如何在 graphql 查询或突变中使用 JWT 进行身份验证。

我阅读了有关授权的指南,但我无法完成。

我需要 GraphQL 方面的帮助以进行 .NET 身份验证。

任何帮助将不胜感激。

谢谢

4

2 回答 2

2

该指南围绕授权。您正在寻找的步骤是身份验证,并且由于可以使用 ASP.Net API 控制器实现 graphql,因此您可以像使用任何控制器一样实现 JWT 身份验证。

这是一个使用 Authorize 属性的示例 grapql 控制器。但是,您可以使用过滤器来实现这一点,或者如果您想要完全控制,自定义中间件。

[Route("api/[controller]")]
[ApiController]
[Authorize]
public class GraphQLController : ControllerBase
{
    private readonly IDocumentExecuter executer;
    private readonly ISchema schema;

    public GraphQLController(IDocumentExecuter executer, ISchema schema)
    {
        this.executer = executer;
        this.schema = schema;
    }

    [HttpPost]
    public async Task<ActionResult<object>> PostAsync([FromBody]GraphQLQuery query)
    {
        var inputs = query.Variables.ToInputs();
        var queryToExecute = query.Query;

        var result = await executer.ExecuteAsync(o => {
            o.Schema = schema;
            o.Query = queryToExecute;
            o.OperationName = query.OperationName;
            o.Inputs = inputs;

            o.ComplexityConfiguration = new GraphQL.Validation.Complexity.ComplexityConfiguration { MaxDepth = 15};
            o.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
        }).ConfigureAwait(false);

        return this.Ok(result);
    }
}

public class GraphQLQuery
{
    public string OperationName { get; set; }
    public string Query { get; set; }
    public Newtonsoft.Json.Linq.JObject Variables { get; set; }
}

在 Startup.cs 中,我配置了 JWT 不记名令牌身份验证。

希望这可以帮助。

于 2018-08-09T19:59:36.203 回答
1

我自己也挣扎了两天。我现在正在使用https://github.com/graphql-dotnet/authorization以及来自此评论的设置(来自我):https ://github.com/graphql-dotnet/authorization/issues/63#issuecomment-553877731

简而言之,您必须正确设置UserContextfor AuthorizationValidationRule,如下所示:

public class Startup
{
    public virtual void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddGraphQLAuth(_ =>
        {
            _.AddPolicy("AdminPolicy", p => p.RequireClaim("Role", "Admin"));
        });
        services.AddScoped<IDependencyResolver>(x => new FuncDependencyResolver(x.GetRequiredService));
        services.AddScoped<MySchema>();
        services
            .AddGraphQL(options => { options.ExposeExceptions = true; })
            .AddGraphTypes(ServiceLifetime.Scoped);
        ...
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        ...
        app.UseMiddleware<MapRolesForGraphQLMiddleware>(); // optional, only when you don't have a "Role" claim in your token
        app.UseGraphQL<MySchema>();
        ...
    }
}

public static class GraphQLAuthExtensions
{
    public static void AddGraphQLAuth(this IServiceCollection services, Action<AuthorizationSettings> configure)
    {
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<IAuthorizationEvaluator, AuthorizationEvaluator>();
        services.AddTransient<IValidationRule, AuthorizationValidationRule>();

        services.AddTransient<IUserContextBuilder>(s => new UserContextBuilder<GraphQLUserContext>(context =>
        {
            var userContext = new GraphQLUserContext
            {
                User = context.User
            };

            return Task.FromResult(userContext);
        }));

        services.AddSingleton(s =>
        {
            var authSettings = new AuthorizationSettings();
            configure(authSettings);
            return authSettings;
        });
    }
}

public class GraphQLUserContext : IProvideClaimsPrincipal
{
    public ClaimsPrincipal User { get; set; }
}

public class MapRolesForGraphQLMiddleware
{
    private readonly RequestDelegate _next;

    public MapRolesForGraphQLMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        // custom mapping code to end up with a "Role" claim
        var metadata = context.User.Claims.SingleOrDefault(x => x.Type.Equals("metadata"));

        if (metadata != null)
        {
            var roleContainer = JsonConvert.DeserializeObject<RoleContainer>(metadata.Value);
            (context.User.Identity as ClaimsIdentity).AddClaim(new Claim("Role", string.Join(", ", roleContainer.Roles)));
        }

        await _next(context);
    }
}

public class RoleContainer
{
    public String[] Roles { get; set; }
}
于 2019-11-14T13:08:49.297 回答