2017-05-11 34 views
5

我正在使用OWIN和OpenID Connect針對Azure AD測試Web項目。我使用的許多代碼從這個樣本:https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnectTokenCache.BeforeAccess上的HttpContext.Current爲空

我已經在那裏我得到這個文件的第27行空的異常問題:https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect/blob/master/TodoListWebApp/Utils/NaiveSessionCache.cs

我得到的異常,因爲HttpContext.Current爲null。

我可以看到Load()是從BeforeAccessNotification()中調用的。

我的框架版本是4.5.2,我在我的web.config中有<httpRuntime targetFramework="4.5.2" ... >

爲什麼HttpContext.Current在此上下文中爲null?


更新時間:

唯一的區別我從樣品已經是我的我的控制器上的ActionResult不是異步。 我使用標準ActionResult中的.Wait()調用異步任務中的AcquireTokenSilentAsync。 我在CMS內部工作,不允許使用異步ActionResults。


這OnAuthorizationCodeReceived:

private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context) 
    { 
     var code = context.Code; 

     var credential = new ClientCredential(ClientId, AppKey); 

     var userObjectID = 
      context.AuthenticationTicket.Identity.FindFirst(
       "http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 

     var authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID)); 

     var uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)); 

     var result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, GraphUrl); 
    } 

這是堆棧跟蹤:

[NullReferenceException: Object reference not set to an instance of an object.] 
    MyTest.NaiveSessionCache.Load() in C:\Workspace\MyTest\src\Website\NaiveSessionCache.cs:26 
    MyTest.NaiveSessionCache.BeforeAccessNotification(TokenCacheNotificationArgs args) in C:\Workspace\MyTest\src\Website\NaiveSessionCache.cs:53 
    Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache.OnBeforeAccess(TokenCacheNotificationArgs args) +94 
    Microsoft.IdentityModel.Clients.ActiveDirectory.<RunAsync>d__55.MoveNext() +3751 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.IdentityModel.Clients.ActiveDirectory.<AcquireTokenByAuthorizationCodeCommonAsync>d__48.MoveNext() +479 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.IdentityModel.Clients.ActiveDirectory.<AcquireTokenByAuthorizationCodeAsync>d__30.MoveNext() +386 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +31 
    MyTest.<OnAuthorizationCodeReceived>d__12.MoveNext() in C:\Workspace\MyTest\src\Website\Startup.cs:86 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +14139265 
    Microsoft.Owin.Security.OpenIdConnect.<AuthenticateCoreAsync>d__1a.MoveNext() +5965 
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +31 
    Microsoft.Owin.Security.OpenIdConnect.<AuthenticateCoreAsync>d__1a.MoveNext() +7305 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.Owin.Security.Infrastructure.<BaseInitializeAsync>d__0.MoveNext() +824 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.Owin.Security.Infrastructure.<Invoke>d__0.MoveNext() +334 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__5.MoveNext() +204 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.Owin.Security.Infrastructure.<Invoke>d__0.MoveNext() +777 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__5.MoveNext() +204 
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +14139120 
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 
    Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<DoFinalWork>d__2.MoveNext() +194 
    Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +96 
    System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +363 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +157 
+2

當你調用它的線程發起網絡調用線程之外它通常是空。你能告訴我們你是否做了一些改變或共享調用堆棧來查看調用的起源地點? –

+0

已更新問題 –

+0

我無法使其工作,因此我停止使用會話,現在正在使用HttpRuntime.Cache。我基本上只是用HttpRuntime.Cache [CacheId]替換了HttpContext.Current.Session [CacheId]。似乎運作良好。 –

回答

2

我明白了。您必須通過HttpContextBase來創建會話緩存對象。 HttpContext.Current變爲空,因爲它在不同的線程上執行。

using Microsoft.IdentityModel.Clients.ActiveDirectory; 
using System.Threading; 
using System.Web; 

namespace AzureADWebApp 
{ 
public class NaiveSessionCache: TokenCache 
{ 
    private static ReaderWriterLockSlim SessionLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); 
    string UserObjectId = string.Empty; 
    string CacheId = string.Empty; 
    HttpContextBase HttpContext = null; 
    public MSALSessionCache(string userId, HttpContextBase httpContext) 
    { 
     UserObjectId = userId; 
     CacheId = UserObjectId + "_TokenCache"; 
     this.HttpContext = httpContext; 
     this.AfterAccess = AfterAccessNotification; 
     this.BeforeAccess = BeforeAccessNotification; 
     Load(); 
    } 

    public void Load() 
    { 
     SessionLock.EnterReadLock(); 
     this.Deserialize((byte[])HttpContext.Session[CacheId]); 
     SessionLock.ExitReadLock(); 
    } 

    public void Persist() 
    { 
     SessionLock.EnterWriteLock(); 

     // Optimistically set HasStateChanged to false. We need to do it early to avoid losing changes made by a concurrent thread. 
     this.HasStateChanged = false; 

     // Reflect changes in the persistent store 
     HttpContext.Session[CacheId] = this.Serialize(); 
     SessionLock.ExitWriteLock(); 
    } 

    // Empties the persistent store. 
    public override void Clear() 
    { 
     base.Clear(); 
     HttpContext.Session.Remove(CacheId); 
    } 

    // Triggered right before ADAL needs to access the cache. 
    // Reload the cache from the persistent store in case it changed since the last access. 
    void BeforeAccessNotification(TokenCacheNotificationArgs args) 
    { 
     Load(); 
    } 

    // Triggered right after ADAL accessed the cache. 
    void AfterAccessNotification(TokenCacheNotificationArgs args) 
    { 
     // if the access operation resulted in a cache update 
     if (this.HasStateChanged) 
     { 
      Persist(); 
     } 
    } 
} 
} 

並在你的AuthenticationCodeReceived通知象下面這樣的附加參數創建NaiveSessionCache對象:

new NaiveSessionCache(userObjectID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase)); 
1

我不知道,如果它是你的情況,但有時的HttpContext的根本原因.Current null是web.config中的缺失鍵:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

1

通過添加異步調用的等待,您正在旋轉HTTPContext.Current爲空的另一個線程。您可能需要調整nativesession提供程序以將httpcontext作爲參數,或者更改程序流以使用await運算符在單個線程中完成此工作,以便可以適當地訪問這些變量。

2

ADAL爲從3.13.0版開始的所有異步方法添加configureAwait(false),這會導致NaiveSession中的HttpContext.Current變爲NULL,因爲它很可能在新線程中。 你可以使用3.12.0版本的ADAL,它工作正常。

相關問題