0

私はApiControllerから継承しているベースAPIを持っています。私はExecuteAsyncをオーバーライドし、Principal.Claims varに格納されているデータの一部を使用したいと考えています。 base.ExecuteAsync()を呼び出す前に空であり、呼び出した後に遅すぎます。私はこれを助けるために他に何かを見いだすことはありませんか?ApiControllerはUser.Claimsにアクセスするためにオーバーライドします

public class ApiControllerBase : ApiController 
{ 
    public MyUser CurrentUser { get; set; } 

    public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) 
    { 
     // principal.claims is empty 
     ClaimsPrincipal principal = (ClaimsPrincipal)RequestContext.Principal; // principal.claims is empty 

     var rv = base.ExecuteAsync(controllerContext, cancellationToken); 

     // principal.claims is now populated but the controller.action that inherits from this basecontroller has already fired and thrown an exception since CurrentUser is null. 
     principal = (ClaimsPrincipal)RequestContext.Principal; 
    } 
} 
+2

この方法をオーバーライドする必要がありますか?達成したい行動は? – MaKCbIMKo

+0

オーバーライドするパイプラインに別のメソッドが見つかりませんでした。最終的な目標は、ベースのApiControllerにいくつかのプロパティを持たせて、継承するコントローラがそれらを使用できるようにすることです。これらのプロパティをロードするために必要な情報は、Principal.Claimsコレクションにあります。 – user3953989

答えて

2

あなたのコントローラ内での請求にアクセスする必要がある場合は、次の操作を行うことができます。その後、

public class MyUser 
{ 
    private readonly ClaimsIdentity _identity; 

    public SeaUser(ClaimsIdentity identity) 
    { 
     _identity= identity; 
    } 

    public IEnumerable<Claim> Claims { get { return _identity.Claims; } } 
} 

public abstract class BaseController : ApiController 
{ 
    private MyUser _user; 

    public new MyUser User 
    { 
     get 
     { 
      return _user ?? (_user = User.Identity != null 
            ? new MyUser((ClaimsIdentity)User.Identity) 
            : null); } 
     } 
    } 
} 

そして、あなたが必要な場所Userプロパティを使用します。要求を仮定

がApiController範囲に入り、操作順序は以下の通りである:

  • ApiControllerのExecuteAsyncメソッドが呼び出されます。
  • ApiControllerのInitializeメソッドが呼び出されます。
  • 登録されたアクションセレクタが取得されます。
  • 登録されたアクションセレクタのSelectActionメソッドが呼び出されます。 アクションメソッドが1つしか一致しない場合、パイプラインは続行されます。
  • 選択したアクションのすべての登録済みフィルタが取得されます。
  • 認証フィルターが呼び出されます。承認フィルタは、
    は、パイプラインを継続して実行させるか、パイプラインを終了するかを決定することができます( )。
  • 許可フィルターが要求を終了しなかった場合は、アクション パラメーターのバインディングが実行されます。
  • ApiController.ModelStateが設定されています。
  • アクションフィルタが呼び出されます。アクションフィルタは、 のいずれかを決定してパイプラインの実行を継続させ、パイプラインを終了させます。
  • アクションフィルターが要求を終了しなかった場合、登録されたアクション 呼び出し元が検索されます。
  • 登録されたAction InvokerのInvokeActionAsyncメソッドは、選択されたアクションメソッドを呼び出すために呼び出される です。

注:認可フィルタの実行からアクションメソッドの実行まで例外が発生した場合、例外フィルタが呼び出されます。

この中にはさらにいくつかのことがありますが、これは完全なビューに非常に近いものです。詳細についてはApiController source codeをご覧ください。これは、私の作品

+0

+1これは動作しますが、上記のように実装する方法があるかどうかを知りたいと思います。 – user3953989

+0

私は答えにいくつかのノートを追加しました。 WebAPIの実行パイプラインによると、 'ExecuteAsync'が呼び出される前にプリンシパルを取得することは不可能です。これは、このメソッド内で初期化されるためです。 – MaKCbIMKo

0

アクションを実行するたびに呼び出されるOnActionExecuting()をオーバーライドできます。

public override void OnActionExecuting(ActionExecutingContext context) 
    { 
     var user = context.HttpContext.User; 
     //store user.Claims in property so inherited controllers have access 
     base.OnActionExecuting(context); 
    } 
+0

このメソッドはSystem.Web.Http.ApiControllerに存在しません – user3953989

+0

おっと、ごめんなさい。私のアプリケーションはASP.Net Core 1.0を使用しています。新しいコントローラクラスがあります –

0

(のThread.CurrentPrincipal)

public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) 
{ 
    var principal = Thread.CurrentPrincipal as ClaimsPrincipal; 
    return base.ExecuteAsync(controllerContext, cancellationToken); 
} 

私はIAppBuilder(Startup.Configuration)に登録された順序が重要であるかどうかわからないんだけど、私は登録最初に認証ミドルウェアです。

+0

私の場合、基本実装を実行する前にprincipal.Claims.Any()**がfalseを返します。 – user3953989

+0

別の段階でクレームを取り戻すことができますか?そうでない場合は、チケットを作成したときにクレームが追加されたことを100%確信していますか? – Frode

+0

はい。私が代わりに行う場合 var rv = base.ExecuteAsync(controllerContext、cancellationToken); principal.Claims //これに値があります。 return rv; – user3953989

関連する問題