2013-02-23 5 views
4

프로젝트에 Asp.Net WebAPI를 사용하고 있습니다. 저는 현재 인증 및 권한 부여 작업을하고 있습니다.DeletingHandler에서 ApiController 유형에 액세스

요청의 HTTP 인증 헤더를 확인하고 내 ID 및 사용자 프로필을 작성하는 messageHandler가 있습니다. 그러나 컨트롤러 액션 (또는 컨트롤러 만)에 액션이 요구할 수있는 클레임을 추가하고 싶습니다. (사용자가 가질 수있는 많은 주장을 가지고 있기 때문에로드하고 싶지 않습니다.)

예컨대 : 내가 속성을보고 다시 DB에서 필요한 경우에만 내용에 따라 주장을 가져올 수 있도록하려면 인증 메시지 핸들러 내부

public class MyController : ApiController 
{ 
    [LoadClaims("SomeClaim", "SomeOtherClaim", "etc")] 
    public string Get() 
    { 
     if (HasClaim("SomeClaim")) 
      return "Awesome"; 

     return "Bummer"; 
    } 
} 

. 이를 위해 나는 루트를 기반으로 컨트롤러와 액션이 무엇을하는지 알아야합니다.

protected override Task<HttpResponseMessage> SendAsync(
      HttpRequestMessage request, CancellationToken cancellationToken) 
     { 
... 

      var routeData = request.GetRouteData(); 
      object controllerName; 
      object actionName; 
      routeData.Values.TryGetValue("controller", out controllerName); 
... 

그래서 알 수 있습니다. 하지만 지금은이를 반영 할 수있는 Type으로 바꾸어야합니다.하지만 컨트롤러 이름 (전체 클래스 이름 또는 네임 스페이스조차도 아님) 만 있으면됩니다. 어떻게 이것을 속성 등을 얻기 위해 반영 할 수있는 것으로 변환 할 수 있습니까?

WebAPI 스택이 어떻게 수행되는지 보려면 DefaultHttpControllerSelector을보고 있는데 HttpControllerTypeCache을 사용하는 것으로 보입니다. 이것은 내부 클래스이므로 인스턴스를 만들 수 없습니다. 목표 컨트롤러 유형을 얻는 올바른 방법은 무엇입니까?

답변

6

전역 서비스 위치 지정자를 사용하여 직접 유형 확인 프로그램에 액세스 할 수 있습니다.

var controllerTypeResolver = GlobalConfiguration.Configuration.Services.GetHttpControllerTypeResolver(); 
var controllerTypes = controllerTypeResolver.GetControllerTypes(GlobalConfiguration.Configuration.Services.GetAssembliesResolver()); 
var controllerType = controllerTypes.SingleOrDefault(ct => ct.Name == string.Format("{0}Controller", controllerName)); 

컨트롤러 선택기와 같은 결과 캐싱이 필요할 수 있습니다. 그러나이 방법이 효과적입니다.

그러나

당신은 컨트롤러보다는 위임 핸들러에 앉아 사용자 정의 인증 필터에이 논리를 이동 더 좋을 수 있습니다. 컨트롤러 유형을 알고 있어야 ControllerSelector를 정상적으로 작동시킬 수 있습니다. 아마도로드 클레임 특성을 권한 동작 필터 특성으로 변환 한 경우 매개 변수로 전달 된 클레임을로드하고 그곳에서 클레임 및 클레임을 설정하면됩니다.

+0

+1. 사용자 정의 인증 필터는 컨트롤러에 대해 필요한 모든 정보가 포함 된 작업 컨텍스트에서 최상의 접근 방식처럼 보입니다. – Despertar

+0

좋습니다. 승인 필터로 사용하지 않은 이유는 액션 메서드에서 사용하기 위해 클레임을 미리로드하고,이를 기반으로하는 인증을 미리로드하려고하기 때문입니다. 그러나 당신은 좋은 점을 제기합니다 - 제가 액션 필터에 똑같은 것을 구현할 수 있다면 왜이 모든 일을 할 수 있습니까? –

+0

사실, 단순한 액션 필터 OnExecuting을 사용하여 정직하게 될 수 있습니다. 사용자는 잠재적으로 얼마나 많은 클레임을 제기합니까? 나는 지금까지 관계없이 모든 것을로드하라는 충고에 저항했습니다 ... 클레임이 포함 된 세션 토큰을 사용하는 경우 각 요청에 대해 주체 및 클레임을 수화하기 위해 데이터베이스를 치는 것을 피할 수 있지만 DB 매번 단순히 성능 튜닝을하는 것이 최선의 방법 일 때마다 서버 캐시 또는 분산 메모리 캐시를 사용하여 성능을 향상시킬 수 있습니다. –

1

당신이 아직 설정하는 경우 DelegatingHandler 당신이 컨트롤러 선택기 인스턴스 자체가 방법이 더 효율적 which'll 얻을 수 :

var controllerSelector = GlobalConfiguration.Configuration.Services.GetHttpControllerSelector(); 
var controllerDescriptor = controllerSelector.SelectController(request); 
+1

내 DelegatingHandler 내에서 GetHttpControllerSelector를 호출하면 TypeInitializationException이 발생합니다. " 'System.Web.HttpGlobalConfiguration.CS $ <> 9__CachedAnonymousMethodDelegate2'필드에 액세스하는 'System.Web.Http.GlobalConfiguration..ctor()'메서드로 시도하지 못했습니다."사용자 지정 HttpControllerSelector를 명시 적으로 구성하지 않았으므로 가정합니다 기본 선택기를 검색하고 있습니다. 내가 뭔가 잘못하고 있는거야? –

관련 문제