ASP.NET Core SignalR에서 허브 필터 사용
허브 필터:
- ASP.NET Core 5.0 이상에서 사용할 수 있습니다.
- 클라이언트에서 허브 메서드를 호출하기 전과 후에 논리를 실행할 수 있습니다.
이 문서에서는 허브 필터를 작성하고 사용하기 위한 지침을 제공합니다.
허브 필터 구성
허브 필터는 전역적으로 또는 허브 유형별로 적용할 수 있습니다. 필터가 추가되는 순서는 필터가 실행되는 순서입니다. 글로벌 허브 필터는 로컬 허브 필터 전에 실행됩니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR(options =>
{
// Global filters will run first
options.AddFilter<CustomFilter>();
}).AddHubOptions<ChatHub>(options =>
{
// Local filters will run second
options.AddFilter<CustomFilter2>();
});
}
허브 필터는 다음 방법 중 하나로 추가할 수 있습니다.
구체적인 형식으로 필터를 추가합니다.
hubOptions.AddFilter<TFilter>();
DI(종속성 주입) 또는 활성화된 형식에서 해결됩니다.
런타임 형식으로 필터를 추가합니다.
hubOptions.AddFilter(typeof(TFilter));
DI 또는 활성화된 형식에서 해결됩니다.
인스턴스별로 필터를 추가합니다.
hubOptions.AddFilter(new MyFilter());
이 인스턴스는 싱글톤처럼 사용됩니다. 모든 허브 메서드 호출은 동일한 인스턴스를 사용합니다.
허브 필터는 허브 호출당 생성 및 삭제됩니다. 필터에 글로벌 상태를 저장하거나 상태를 저장하지 않으려는 경우 성능 향상을 위해 허브 필터 형식을 DI에 싱글톤으로 추가합니다. 또는 가능한 경우 필터를 인스턴스로 추가합니다.
허브 필터 만들기
IHubFilter
에서 상속되는 클래스를 선언하여 필터를 만들고 InvokeMethodAsync
메서드를 추가합니다. OnConnectedAsync
및 OnDisconnectedAsync
허브 메서드를 각각 래핑하기 위해 필요에 따라 구현할 수 있는 OnConnectedAsync
및 OnDisconnectedAsync
도 있습니다.
public class CustomFilter : IHubFilter
{
public async ValueTask<object> InvokeMethodAsync(
HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
{
Console.WriteLine($"Calling hub method '{invocationContext.HubMethodName}'");
try
{
return await next(invocationContext);
}
catch (Exception ex)
{
Console.WriteLine($"Exception calling '{invocationContext.HubMethodName}': {ex}");
throw;
}
}
// Optional method
public Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next)
{
return next(context);
}
// Optional method
public Task OnDisconnectedAsync(
HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next)
{
return next(context, exception);
}
}
필터는 미들웨어와 매우 유사합니다. next
메서드는 다음 필터를 호출합니다. 최종 필터는 허브 메서드를 호출합니다. 필터는 next
에서 결과를 반환하기 전에 허브 메서드가 호출된 후 대기 중인 next
의 결과 및 실행 논리를 저장할 수도 있습니다.
필터에서 허브 메서드 호출을 건너뛰려면 next
를 호출하는 대신 HubException
형식의 예외를 throw합니다. 결과가 예상되면 클라이언트에서 오류가 발생합니다.
허브 필터 사용
필터 논리를 작성할 때 허브 메서드 이름을 확인하는 대신 허브 메서드의 특성을 사용하여 제네릭으로 만듭니다.
허브 메서드 인수에서 금지된 구를 확인하고 찾은 모든 구를 ***
로 바꾸는 필터를 고려합니다.
이 예제에서는 LanguageFilterAttribute
클래스가 정의되어 있다고 가정합니다. 클래스에는 특성을 사용할 때 설정할 수 있는 FilterArgument
라는 속성이 있습니다.
정리할 문자열 인수가 있는 허브 메서드에 특성을 배치합니다.
public class ChatHub { [LanguageFilter(filterArgument = 0)] public async Task SendMessage(string message, string username) { await Clients.All.SendAsync("SendMessage", $"{username} says: {message}"); } }
허브 필터를 정의하여 특성을 확인하고 허브 메서드 인수의 금지된 구를
***
로 대체합니다.public class LanguageFilter : IHubFilter { // populated from a file or inline private List<string> bannedPhrases = new List<string> { "async void", ".Result" }; public async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next) { var languageFilter = (LanguageFilterAttribute)Attribute.GetCustomAttribute( invocationContext.HubMethod, typeof(LanguageFilterAttribute)); if (languageFilter != null && invocationContext.HubMethodArguments.Count > languageFilter.FilterArgument && invocationContext.HubMethodArguments[languageFilter.FilterArgument] is string str) { foreach (var bannedPhrase in bannedPhrases) { str = str.Replace(bannedPhrase, "***"); } var arguments = invocationContext.HubMethodArguments.ToArray(); arguments[languageFilter.FilterArgument] = str; invocationContext = new HubInvocationContext(invocationContext.Context, invocationContext.ServiceProvider, invocationContext.Hub, invocationContext.HubMethod, arguments); } return await next(invocationContext); } }
Startup.ConfigureServices
메서드에 허브 필터를 등록합니다. 모든 호출에 대해 금지된 구 목록을 다시 활성화하지 않으려면 허브 필터가 싱글톤으로 등록됩니다.public void ConfigureServices(IServiceCollection services) { services.AddSignalR(hubOptions => { hubOptions.AddFilter<LanguageFilter>(); }); services.AddSingleton<LanguageFilter>(); }
HubInvocationContext 개체
HubInvocationContext
에는 현재 허브 메서드 호출에 대한 정보가 포함되어 있습니다.
속성 | 설명 | Type |
---|---|---|
Context |
HubCallerContext 에는 연결에 대한 정보가 포함되어 있습니다. |
HubCallerContext |
Hub |
이 허브 메서드 호출에 사용되는 허브의 인스턴스입니다. | Hub |
HubMethodName |
호출되는 허브 메서드의 이름입니다. | string |
HubMethodArguments |
허브 메서드에 전달되는 인수 목록입니다. | IReadOnlyList<string> |
ServiceProvider |
이 허브 메서드 호출에 대한 범위가 지정된 서비스 공급자입니다. | IServiceProvider |
HubMethod |
허브 메서드 정보입니다. | MethodInfo |
HubLifetimeContext 개체
HubLifetimeContext
에는 OnConnectedAsync
및 OnDisconnectedAsync
허브 메서드에 대한 정보가 포함되어 있습니다.
속성 | 설명 | Type |
---|---|---|
Context |
HubCallerContext 에는 연결에 대한 정보가 포함되어 있습니다. |
HubCallerContext |
Hub |
이 허브 메서드 호출에 사용되는 허브의 인스턴스입니다. | Hub |
ServiceProvider |
이 허브 메서드 호출에 대한 범위가 지정된 서비스 공급자입니다. | IServiceProvider |
권한 부여 및 필터
허브 필터 전에 실행되는 허브 메서드의 특성에 권한을 부여합니다.
ASP.NET Core
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기