У меня есть несколько Asp. Net Core Web API, которые используют аутентификацию Bearer и IdentityServer4.AccessTokenValidation
промежуточное ПО для анализа токенов, аутентификации пользователя и создания заявок. Это прекрасно работает для HTTP-запросов.
Я нахожусь в процессе настройки этих API-интерфейсов, чтобы они также были конечными точками MassTransit (как для публикации, так и для использования сообщений) с использованием RabbitMQ в качестве транспорта. Я следовал инструкциям здесь для добавления MassTransit к API и для настройки потребителей сообщений. Типичный рабочий процесс будет выглядеть примерно так:
HTTP-запрос к API> Publi sh сообщение на MassTransit> RabbitMQ> Сообщение используется в другом API
What I'm Изо всех сил пытаюсь понять, как я могу создать ClaimsPrincipal
при потреблении сообщений с шины, чтобы я знал, для какого пользователя выполнять действия от имени? Там, где это не HTTP-запрос, не вызывается AuthenticationHandler.
Что я пробовал до сих пор:
Я думал, что подойду к этому, передав токен (и / или отдельные значения претензий) в заголовках сообщений. Часть publi sh выглядела достаточно легко, так как MassTransit позволяет добавлять любое количество пользовательских заголовков при публикации сообщений с использованием MassTransit.PublishContextExecuteExtensions.Publish
. Это позволило мне получать на транспорт сообщения с информацией, идентифицирующей пользователя, и эту информацию можно просмотреть у потребителя, просмотрев заголовки вручную, например
public class SomeEventConsumer : IConsumer<SomeEventData>
{
public async Task Consume(ConsumeContext<SomeEventData> context)
{
var token = context.Headers["token"];
}
}
. В этот момент я мог взять токен и вызвать Introspection. конечная точка в Identity Server вручную, но тогда мне нужно:
- Каждый раз делать это с каждым потребителем, а затем ...
- ... передавать эту информацию в logi c классы и c вручную вместо использования
IHttpContextAccessor.HttpContext.User.Claims
или путем обобщения утверждений и использования Dependency Injection.
К точке 1 я создал новое пользовательское промежуточное ПО ...
public class AuthenticationFilter<T> : IFilter<ConsumeContext<T>> where T : class
{
public void Probe(ProbeContext context)
{
var scope = context.CreateFilterScope("authenticationFilter");
}
public async Task Send(ConsumeContext<T> context, IPipe<ConsumeContext<T>> next)
{
var token = context.Headers.Where(x => x.Key == "token").Select(x => x.Value.ToString()).Single();
// TODO: Call token introspection
await next.Send(context);
}
}
public class AuthenticationFilterSpecification<T> : IPipeSpecification<ConsumeContext<T>> where T : class
{
public void Apply(IPipeBuilder<ConsumeContext<T>> builder)
{
var filter = new AuthenticationFilter<T>();
builder.AddFilter(filter);
}
public IEnumerable<ValidationResult> Validate()
{
return Enumerable.Empty<ValidationResult>();
}
}
public class AuthenticationFilterConfigurationObserver : ConfigurationObserver, IMessageConfigurationObserver
{
public AuthenticationFilterConfigurationObserver(IConsumePipeConfigurator receiveEndpointConfigurator) : base(receiveEndpointConfigurator)
{
Connect(this);
}
public void MessageConfigured<TMessage>(IConsumePipeConfigurator configurator)
where TMessage : class
{
var specification = new AuthenticationFilterSpecification<TMessage>();
configurator.AddPipeSpecification(specification);
}
}
public static class AuthenticationExtensions
{
public static void UseAuthenticationFilter(this IConsumePipeConfigurator configurator)
{
if (configurator == null)
{
throw new ArgumentNullException(nameof(configurator));
}
_ = new AuthenticationFilterConfigurationObserver(configurator);
}
}
... и затем добавил это в конвейер ...
IBusControl CreateBus(IServiceProvider serviceProvider)
{
return Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Host("rabbitmq://localhost");
cfg.UseAuthenticationFilter();
// etc ...
});
}
И вот где я застрял. Я не знаю, как аутентифицировать пользователя для объема запроса. Где это не HTTP-запрос, я не уверен, что здесь лучше. Любые предложения или указатели будут с благодарностью приняты. Спасибо ...