2017-05-30 18 views
2

私は.NETコアWeb APIを構築しています。このAPIはAADを使用して保護されており、ADALを使用して、代わってフローを使用して下流のAPIを呼び出します。このAzureのサンプルに似て:このようなシナリオで使用されるべきであるトークンキャッシュするためのベストプラクティスWeb APIの推奨ADALトークンキャッシュ?

https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof

何ですか?

  • デフォルトのキャッシュは受け入れられますか?

  • あなたはキャッシュを持っていないでしょうか? (nullの権威、)

    AuthenticationContext authContext =新しい AuthenticationContext

  • あなた自身 を構築する必要がある場合は、次に使用するには良いリファレンス実装はありますか?

答えて

4

使用する正しいトークンキャッシュは、非常に主観的であり、アーキテクチャ、パフォーマンス要件などに大きく依存します。

ADALで使用される既定のキャッシュはインメモリキャッシュです。つまり、APIが受け取る要求間で永続的にキャッシュされないことがあります。さらに、ADAL.NETで使用される既定のキャッシュは静的クラスです。つまり、APIに対する2つの異なる要求が同じキャッシュオブジェクトを取得する可能性があります。したがって、デフォルトのADALキャッシュを使用することはお勧めできません。これは実際にあなたのWebサーバーの仕組みによって異なります。

代わりに、パフォーマンスヒットを管理したり、独自のトークンキャッシュを実装したりできる場合は、nullをトークンキャッシュとして渡すことをおすすめします。

独自のキャッシュを実装したい場合は、受信リクエストごとに(ADAL経由で)送信HTTPリクエストを送信する必要がなくなります。 .NETエンティティフレームワークを使用したサンプルADALキャッシュ実装はhere利用でき、同様に下にコピーされます。

using Microsoft.IdentityModel.Clients.ActiveDirectory; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Data.Entity; 
using System.Linq; 
using System.Web; 

namespace TodoListWebApp.DAL 
{ 

    public class PerWebUserCache 
    { 
     [Key] 
     public int EntryId { get; set; } 
     public string webUserUniqueId { get; set; } 
     public byte[] cacheBits { get; set; } 
     public DateTime LastWrite { get; set; } 
    } 

    public class EFADALTokenCache: TokenCache 
    { 
     private TodoListWebAppContext db = new TodoListWebAppContext(); 
     string User; 
     PerWebUserCache Cache; 

     // constructor 
     public EFADALTokenCache(string user) 
     { 
      // associate the cache to the current user of the web app 
      User = user; 

      this.AfterAccess = AfterAccessNotification; 
      this.BeforeAccess = BeforeAccessNotification; 
      this.BeforeWrite = BeforeWriteNotification; 

      // look up the entry in the DB 
      Cache = db.PerUserCacheList.FirstOrDefault(c => c.webUserUniqueId == User); 
      // place the entry in memory 
      this.Deserialize((Cache == null) ? null : Cache.cacheBits); 
     } 

     // clean up the DB 
     public override void Clear() 
     { 
      base.Clear(); 
      foreach (var cacheEntry in db.PerUserCacheList) 
       db.PerUserCacheList.Remove(cacheEntry); 
      db.SaveChanges(); 
     } 

     // Notification raised before ADAL accesses the cache. 
     // This is your chance to update the in-memory copy from the DB, if the in-memory version is stale 
     void BeforeAccessNotification(TokenCacheNotificationArgs args) 
     { 
      if (Cache == null) 
      { 
       // first time access 
       Cache = db.PerUserCacheList.FirstOrDefault(c => c.webUserUniqueId == User); 
      } 
      else 
      { // retrieve last write from the DB 
       var status = from e in db.PerUserCacheList 
          where (e.webUserUniqueId == User) 
          select new 
          { 
           LastWrite = e.LastWrite 
          }; 
       // if the in-memory copy is older than the persistent copy 
       if (status.First().LastWrite > Cache.LastWrite) 
       //// read from from storage, update in-memory copy 
       { 
        Cache = db.PerUserCacheList.FirstOrDefault(c => c.webUserUniqueId == User); 
       } 
      } 
      this.Deserialize((Cache == null) ? null : Cache.cacheBits); 
     } 
     // Notification raised after ADAL accessed the cache. 
     // If the HasStateChanged flag is set, ADAL changed the content of the cache 
     void AfterAccessNotification(TokenCacheNotificationArgs args) 
     { 
      // if state changed 
      if (this.HasStateChanged) 
      { 
       Cache = new PerWebUserCache 
       { 
        webUserUniqueId = User, 
        cacheBits = this.Serialize(), 
        LastWrite = DateTime.Now 
       }; 
       //// update the DB and the lastwrite     
       db.Entry(Cache).State = Cache.EntryId == 0 ? EntityState.Added : EntityState.Modified;     
       db.SaveChanges(); 
       this.HasStateChanged = false; 
      } 
     } 
     void BeforeWriteNotification(TokenCacheNotificationArgs args) 
     { 
      // if you want to ensure that no concurrent write take place, use this notification to place a lock on the entry 
     } 
    } 

} 
+0

はちょうどこの上でつまずいた、それが必要なあなたがクリア()メソッド、そうでない場合、値にキャッシュ=ヌルをマークすることをイマイチ変数から削除されることはありませんし、BeforeAccessメソッドでは、最初のifが渡されるべきではないときに渡されます。したがって、間違った資格情報のトークンを取得することもできます。 –

関連する問題