Как реализовать авторизацию с использованием GraphQL.NET на уровне функций Resolver?
Я ищу пример кода и примеры того, как реализовать авторизацию на уровне функции распознавателя, используя GraphQL.NET и ASP.NET CORE 2.
В основном я пытаюсь предотвратить выполнение запроса, если запрос не авторизован.
Может кто-нибудь помочь мне получить некоторые хорошие учебники или примеры кода в качестве ссылки для реализации.
1 ответ
Для https://github.com/graphql-dotnet/authorization, страница для AspNetCore
не был выпущен, см. Add GraphQL.Server.Authorization.AspNetCore NuGet пакет # 171.
Вы можете реализовать Authorization.AspNetCore для собственного использования.
После реализации Authorization.AspNetCore
Вы можете настроить Authorize
лайк:
Startup.cs
public class Startup { public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment) { Configuration = configuration; Environment = hostingEnvironment; } public IConfiguration Configuration { get; } public IHostingEnvironment Environment { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddAuthentication(option => { option.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme); services.AddGraphQL(options => { options.EnableMetrics = true; options.ExposeExceptions = Environment.IsDevelopment(); //options. }) .AddGraphQLAuthorization(options => { options.AddPolicy("Authorized", p => p.RequireAuthenticatedUser()); //var policy = new AuthorizationPolicyBuilder() // . //options.AddPolicy("Authorized", p => p.RequireClaim(ClaimTypes.Name, "Tom")); }); //.AddUserContextBuilder(context => new GraphQLUserContext { User = context.User }); services.AddSingleton<MessageSchema>(); services.AddSingleton<MessageQuery>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseAuthentication(); app.UseGraphQL<MessageSchema>("/graphql"); app.UseGraphQLPlayground(new GraphQLPlaygroundOptions() { Path = "/ui/playground" }); app.UseGraphiQLServer(new GraphiQLOptions { GraphiQLPath = "/ui/graphiql", GraphQLEndPoint = "/graphql" }); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } }
схема
public class MessageQuery : ObjectGraphType<Message> { public MessageQuery() { Field(o => o.Content).Resolve(o => "This is Content").AuthorizeWith("Authorized"); Field(o => o.SentAt); Field(o => o.Sub).Resolve(o => "This is Sub"); } }
Для полной демонстрации см. GraphQLNet.
Чтобы получить авторизацию 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()
в верхнюю часть конструктора запроса следующим образом:
public class MyQuery : ObjectGraphType
{
public MyQuery(ProductRepository productRepository)
{
this.AuthorizeWith("LoggedIn");
Field<ListGraphType<ProductType>>(
"products",
resolve: context => productRepository.GetAllAsync()
);
}
}
При этом любой неаутентифицированный доступ к вашей конечной точке GraphQL будет отклонен.
Что касается входа в систему, есть много способов сделать это. Вот быстрый пример аутентификации на основе файлов cookie:
Настройте аутентификацию на основе файлов cookie в Startup.cs' ConfigureServices:
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 };
});
}
}