如何在解析器功能级别使用GraphQL.NET实现授权?

时间:2018-11-29 11:02:12

标签: c# asp.net-core-2.0 graphql-dotnet

我正在寻找有关如何使用GraphQL.NET和ASP.NET CORE 2在解析器功能级别实现授权的示例代码和示例。

基本上,如果请求未经授权,我试图阻止查询的执行。

任何人都可以帮助我获得一些好的教程或代码示例,以作为实现的参考。

2 个答案:

答案 0 :(得分:5)

要获得GraphQL.Net在ASP.NET Core中工作的授权,请先安装此软件包:

GraphQL.Server.Authorization.AspNetCore

在Startup.cs中,在ConfigureServices中添加以下内容。确保添加以下using语句:

    using GraphQL.Validation;
    using GraphQL.Server.Authorization.AspNetCore;
public void ConfigureServices(IServiceCollection services)
{
    //... other code

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    services
        .AddTransient<IValidationRule, AuthorizationValidationRule>()
        .AddAuthorization(options =>
        {
            options.AddPolicy("LoggedIn", p => p.RequireAuthenticatedUser());
        });

    //... other code
}

现在,您将可以在解析器级别使用AuthorizeWith()保护该字段。示例:

public class MyQuery : ObjectGraphType
{
    public MyQuery(ProductRepository productRepository)
    {
        Field<ListGraphType<ProductType>>(
            "products",
            resolve: context => productRepository.GetAllAsync() 
        ).AuthorizeWith("LoggedIn");
    }
}

您还可以通过将this.AuthorizeWith()添加到Query构造函数的顶部来保护所有查询,如下所示:

 public class MyQuery : ObjectGraphType
 {
     public MyQuery(ProductRepository productRepository)
     {
         this.AuthorizeWith("LoggedIn");
         Field<ListGraphType<ProductType>>(
             "products",
             resolve: context => productRepository.GetAllAsync() 
         );
     }
 }

这样,将拒绝对GraphQL端点的任何未经身份验证的访问。

就登录某人而言,有很多方法可以做到这一点。这是一个基于Cookie的快速身份验证示例:

在Startup.cs的ConfigureServices中配置基于cookie的身份验证:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(o =>
        {
            o.Cookie.Name = "graph-auth";
        });

使用突变登录某人:

public class Session
{
    public bool IsLoggedIn { get; set; }
}

public class SessionType : ObjectGraphType<Session>
{
    public SessionType()
    {
        Field(t => t.IsLoggedIn);
    }
}

public class MyMutation : ObjectGraphType
{
    public MyMutation(IHttpContextAccessor contextAccessor)
    {
        FieldAsync<SessionType>(
            "sessions",
            arguments: new QueryArguments(
                new QueryArgument<NonNullGraphType<StringGraphType>> { Name = "password" }),
            resolve: async context =>
            {
                string password = context.GetArgument<string>("password");

                // NEVER DO THIS...for illustration purpose only! Use a proper credential management system instead. :-)
                if (password != "123")
                    return new Session { IsLoggedIn = false };

                var principal = new ClaimsPrincipal(new ClaimsIdentity("Cookie"));
                await contextAccessor.HttpContext.SignInAsync(principal, new AuthenticationProperties
                {
                    ExpiresUtc = DateTime.UtcNow.AddMonths(6),
                    IsPersistent = true
                });

                return new Session { IsLoggedIn = true };
            });
    }
}

答案 1 :(得分:1)

对于graphql-dotnet/authorizationMat*的页面尚未发布,请参考Add GraphQL.Server.Authorization.AspNetCore NuGet package #171

您可以实现Authorization.AspNetCore供您自己使用。

实施tree_之后,您可以像这样配置Generators

  • make_move(...)

        template <typename Mat,
                    typename I,
                    typename... Args,
                    template <typename, typename, typename...> class Tup,
                    template <typename, typename, typename...> class Tree,
                    template <typename, typename...> class X>
        void make_move(I i, I j,
                        Tree<I, Tup<I, Mat*, Args...>, Args...>& tree_,
                        X<Mat*, Args...>& Generators, int n, int q) {
            // Make a direct edge between node i and node j
            // by first tracing the path from node j to
            // node i, multiplying all the edge labels along
            // the way and then taking the inverse.
    
    //      // Note: node j is in a deeper level of the tree than node i
            Mat M(n, n);
            M.identity();
    
    
            while (std::get<0>(tree_[j]) != std::get<0>(tree_[i])) {
                FiniteField::dot(M, *std::get<1>(tree_[j]), M, q);
                j = std::get<0>(tree_[j]);
            }
    
    
            M.print();
        }
    
  • 模式

    error: no instance of function template "make_move" matches the argument list
                argument types are: (int, int, std::unordered_map<int, std::tuple<int, Matrix<unsigned int> *>, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<const int, std::tuple<int, Matrix<unsigned int> *>>>>, std::vector<Matrix<unsigned int> *, std::allocator<Matrix<unsigned int> *>>, int, int)
    

有关完整的演示,请参阅GraphQLNet