2013-10-28 3 views
7

My WebAPI 2アプリケーションには、アクセストークンをチェックするカスタム認証フィルタがあります。トークンが存在し、APIに属性がある場合は、そのトークンにマップするユーザーが存在するかどうかを確認します。プリンシパル/ユーザコンテキストをユーザオブジェクトに設定

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

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; 
} 

[現在の実装では、タイプAuthorizeAttributeの属性の中で起こる]これは正常に動作し、私は、メソッドに第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; 
} 

答えて

8

独自のプリンシパルクラスを使用できます。多分何か:

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; 
} 
... 

私はactaullyこのコードを試していないので、タイプミス...

があるかもしれません
+0

なぜ私はGenericPrincipalを拡張するとは思わなかったのですか?うまくいった!ありがとうございました! – ShaneC

7

あなたは役者を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; 
+1

クレームを使用するほうが、フレームワークとの整合性が向上します。または、コードがHttpContextに依存する場合は、とにかくHttpContext.Profileも使用できます。 http://msdn.microsoft.com/en-us/library/system.web.httpcontext.profile(v=vs.110).aspx – user3285954

関連する問題