web-dev-qa-db-ja.com

プリンシパル/ユーザーコンテキストをユーザーオブジェクトに設定する

私のWebAPI2アプリケーションには、アクセストークンをチェックするカスタム認証フィルターがあります。トークンが存在し、APIに属性がある場合、そのトークンにマップするユーザーが存在するかどうかを確認します。

APIの性質上、ほとんどのメソッドは特定のユーザーのコンテキストで実行されます(つまり、ユーザーのプロファイルを更新するための「POSTapi/profile」)。これを行うには、アクセストークンから取得したターゲットユーザーに関する情報が必要です。

[現在の実装、タイプAuthorizeAttributeの属性内で発生]

if( myDBContext.MyUsers.Count( x => x.TheAccessToken == clientProvidedToken ) ){
    IPrincipal principal = new GenericPrincipal( new GenericIdentity( myAccessToken ), new string[] { "myRole" } );
    Thread.CurrentPrincipal = principal;
    HttpContext.Current.User = principal;
    return true;
}

これは正常に機能し、アクセストークンを使用してメソッドで2回目のルックアップを実行できます。 ただし、認証時に既にルックアップを行っているので、別のDB呼び出しを無駄にしたくありません

[やりたいこと(でも明らかにうまくいかない)]

MyUser user = myDBContext.MyUsers.FirstOrDefault( x => x.TheAccessToken == clientProvidedToken );
if( user != null ){
    // Set *SOME* property to the User object, such that it can be
    // access in the body of my controller method
    // (e.g. /api/profile uses this object to load data)
    HttpContext.Current.User = user;
    return true;
}
11
ShaneC

独自のプリンシパルクラスを使用できます。多分次のようなものです:

public class MyPrincipal : GenericPrincipal
{
    public MyPrincipal(IIdentity identity, string[] roles)
        : base(identity, roles)
    {
    }
    public MyUser UserDetails {get; set;}
}

次に、アクションフィルターで次のことができます。

MyUser user = myDBContext.MyUsers.FirstOrDefault( x => x.TheAccessToken == clientProvidedToken );
if(user != null)
{
    MyPrincipal principal = new MyPrincipal( new GenericIdentity( myAccessToken ), new string[] { "myRole" } );
    principal.UserDetails = user;
    Thread.CurrentPrincipal = principal;
    HttpContext.Current.User = principal;
    return true;
}
return false;

その後、実際のメソッドで、現在のユーザーを取得し、タイプがMyPrincipalであるかどうかを確認し、そうである場合はキャストして、UserDetailsにアクセスできます。

...
MyUser currentUser = null;
MyPrincipal curPrincipal = HttpContext.Current.User as MyPrincipal;
if (curPrincipal != null)
{
    currentUser = curPrincipal.UserDetails;
}
...

私はこのコードを実際に試したことがないので、タイプミスがあるかもしれません...

11
user1429080

ClaimsIdentity/ClaimsPrincipalを使用して、後で必要なClaimsをコントローラーに追加できます。たとえば、アクターIDやその他の必要な値などです。

アクターにクレームを設定する例を作成しましたが、それがより適切な場合は、現在のユーザーに直接クレームを設定することもできます。

var identity = new ClaimsIdentity(HttpContext.Current.User.Identity);
identity.Actor = new ClaimsIdentity();
identity.Actor.AddClaim(new Claim("Your", "Values"));

var principal = new ClaimsPrincipal(identity);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = Thread.CurrentPrincipal;
8
Jos Vinke