Authentication 使用JWT使用Asp.net核心进行GraphQL身份验证

Authentication 使用JWT使用Asp.net核心进行GraphQL身份验证,authentication,asp.net-core,graphql,graphql-dotnet,Authentication,Asp.net Core,Graphql,Graphql Dotnet,我使用的是graphql的for包。但我不明白如何在graphql查询或变异中使用JWT进行身份验证 我读了那本书,但没能完成 我需要有关.NET身份验证的GraphQL的帮助 任何帮助都将不胜感激 谢谢本指南是关于授权的。您正在寻找的步骤是身份验证,因为graphql可以使用ASP.NETAPI控制器实现,所以您可以像使用任何控制器一样实现JWT身份验证 下面是一个使用Authorize属性的grapql控制器示例。然而,您可以使用过滤器或者如果您想要完全控制,则可以使用自定义中间件来实现这一

我使用的是graphql的for包。但我不明白如何在graphql查询或变异中使用JWT进行身份验证

我读了那本书,但没能完成

我需要有关.NET身份验证的GraphQL的帮助

任何帮助都将不胜感激


谢谢

本指南是关于授权的。您正在寻找的步骤是身份验证,因为graphql可以使用ASP.NETAPI控制器实现,所以您可以像使用任何控制器一样实现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; }
}
[路由(“api/[控制器]”)]
[ApiController]
[授权]
公共类GraphQLController:ControllerBase
{
私有只读IDocumentExecuter执行器;
私有只读ISchema模式;
公共图形QLController(IDocumentExecuter执行器,ISchema架构)
{
this.executer=执行器;
this.schema=schema;
}
[HttpPost]
公共异步任务PostAsync([FromBody]GraphQLQuery查询)
{
var inputs=query.Variables.ToInputs();
var queryToExecute=query.query;
var result=wait executer.ExecuteAsync(o=>{
o、 模式=模式;
o、 Query=queryToExecute;
o、 OperationName=query.OperationName;
o、 输入=输入;
o、 ComplexityConfiguration=newgraphql.Validation.Complexity.ComplexityConfiguration{MaxDepth=15};
o、 FieldMiddleware.Use();
}).配置等待(错误);
返回这个。Ok(结果);
}
}
公共类GraphQLQuery
{
公共字符串操作名{get;set;}
公共字符串查询{get;set;}
public Newtonsoft.Json.Linq.JObject变量{get;set;}
}
在Startup.cs中,我配置了JWT承载令牌身份验证


希望这能有所帮助。

我自己也挣扎了两天。我现在正在使用此评论中的设置(来自我):

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

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; }
}
公共类启动
{
公共虚拟void配置服务(IServiceCollection服务)
{
...
services.AddGraphQLAuth(\uqlauth=>
{
_.AddPolicy(“AdminPolicy”,p=>p.requirecarel(“角色”,“管理员”);
});
addScope(x=>newFuncDependencyResolver(x.GetRequiredService));
services.addScope();
服务
.AddGraphQL(选项=>{options.exposeeExceptions=true;})
.AddGraphTypes(ServiceLifetime.Scoped);
...
}
public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、IServiceProvider服务提供商)
{
...
app.useMidleware();//可选,仅当您的令牌中没有“角色”声明时
app.UseGraphQL();
...
}
}
公共静态类GraphQLAuthExtensions
{
公共静态void AddGraphQLAuth(此IServiceCollection服务,操作配置)
{
services.AddSingleton();
services.AddSingleton();
services.AddTransient();
services.AddTransient(s=>newusercontextbuilder(context=>
{
var userContext=new GraphQLUserContext
{
User=context.User
};
返回Task.FromResult(userContext);
}));
services.AddSingleton(s=>
{
var authSettings=新授权设置();
配置(authSettings);
返回授权设置;
});
}
}
公共类GraphQLUserContext:IProvideClaimsPrincipal
{
public ClaimsPrincipal用户{get;set;}
}
公共类maprolesforgraphql中间件
{
private readonly RequestDelegate\u next;
公共映射角色ForGraphQlMiddleware(RequestDelegate next)
{
_下一个=下一个;
}
公共异步任务调用(HttpContext上下文)
{
//以“角色”声明结尾的自定义映射代码
var metadata=context.User.Claims.SingleOrDefault(x=>x.Type.Equals(“metadata”);
if(元数据!=null)
{
var roleContainer=JsonConvert.DeserializeObject(metadata.Value);
(context.User.Identity as ClaimsIdentity).AddClaim(新声明(“Role”,string.Join(“,”,roleContainer.Roles));
}
等待下一步(上下文);
}
}
公共类角色容器
{
公共字符串[]角色{get;set;}
}

我不确定我是否理解这两者的关系。使用JWT,您可以根据应用程序对用户进行身份验证。当用户点击控制器操作时,用户已经填充了声明,并且可以与您链接的示例一起使用?但是我们应该使用JWT有效负载授权graphql查询?从第一次查看(没有查看详细信息)开始,链接的示例仅分别使用
IPrincipal
/
ClaimsPrincipal
。您所要做的就是检查用户是否有特定的声明(在本例中)。在请求过程中先前已填充的声明。阅读后,您将声明发送到API,API使用声明和所有其他信息填充用户属性。在这一点上,如果用户通过jwt、cookie或其他我理解的东西进行身份验证,您就不必再担心了。谢谢但在同一个指南中,它展示了如何实现。但是它有很多错误。我可以需要这个吗?以下是实施: