2014-10-20 74 views
2

我試圖使用Thinktecture.IdentityModel中的ResourceAuthorize屬性,但由於沒有owin上下文,所有內容都會停止。缺少owin上下文

我有設置授權管理器

[assembly: OwinStartup(typeof(My.WebApi.Startup))] 

namespace My.WebApi 
{ 
    public class Startup 
    {   
     public void Configuration(IAppBuilder app) 
     { 
      AuthConfig.Configure(app); 
     } 
    } 
} 

public class AuthConfig 
{ 
    public static void Configure(IAppBuilder app) 
    {   
     app.UseResourceAuthorization(new ResourceAuthorizationMiddlewareOptions 
     { 
      Manager = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IResourceAuthorizationManager)) as IResourceAuthorizationManager 
     }); 
    } 
} 

一個owin啓動類,我知道它是檢測和調用。但後來,從IdentityModel打下面的代碼時,我得到一個空指針異常:

public static Task<bool> CheckAccessAsync(this HttpRequestMessage request, IEnumerable<Claim> actions, IEnumerable<Claim> resources) 
    { 
     var authorizationContext = new ResourceAuthorizationContext(
      request.GetOwinContext().Authentication.User ?? Principal.Anonymous, 
      actions, 
      resources); 

     return request.CheckAccessAsync(authorizationContext); 
    } 

我已經通過加強並看到它是由GetOwinContext(引起的)返回null,因爲沒有MS_OwinContextMS_OwinEnvironment財產的請求。

我錯過了什麼?

UPDATE:

我發現我有一個owin.environment屬性可用,但它的`HttpContextWrapper,而不是請求的一部分。

通過圍繞搜索,我發現System.Web.Http.WebHost.HttpControllerHandler看起來像它應該轉換的owin.environmentMS_OwinEnvironment,但顯然,該代碼永遠不會在我的情況下,所謂的內部一些代碼...

internal static readonly string OwinEnvironmentHttpContextKey = "owin.Environment"; 
internal static readonly string OwinEnvironmentKey = "MS_OwinEnvironment"; 

internal static HttpRequestMessage ConvertRequest(HttpContextBase httpContextBase, IHostBufferPolicySelector policySelector) 
{ 
    HttpRequestBase requestBase = httpContextBase.Request; 
    HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethodHelper.GetHttpMethod(requestBase.HttpMethod), requestBase.Url); 
    bool bufferInput = policySelector == null || policySelector.UseBufferedInputStream((object) httpContextBase); 
    httpRequestMessage.Content = HttpControllerHandler.GetStreamContent(requestBase, bufferInput); 
    foreach (string str in (NameObjectCollectionBase) requestBase.Headers) 
    { 
    string[] values = requestBase.Headers.GetValues(str); 
    HttpControllerHandler.AddHeaderToHttpRequestMessage(httpRequestMessage, str, values); 
    } 
    HttpRequestMessageExtensions.SetHttpContext(httpRequestMessage, httpContextBase); 
    HttpRequestContext httpRequestContext = (HttpRequestContext) new WebHostHttpRequestContext(httpContextBase, requestBase, httpRequestMessage); 
    System.Net.Http.HttpRequestMessageExtensions.SetRequestContext(httpRequestMessage, httpRequestContext); 
    IDictionary items = httpContextBase.Items; 
    if (items != null && items.Contains((object) HttpControllerHandler.OwinEnvironmentHttpContextKey)) 
    httpRequestMessage.Properties.Add(HttpControllerHandler.OwinEnvironmentKey, items[(object) HttpControllerHandler.OwinEnvironmentHttpContextKey]); 
    httpRequestMessage.Properties.Add(HttpPropertyKeys.RetrieveClientCertificateDelegateKey, (object) HttpControllerHandler._retrieveClientCertificate); 
    httpRequestMessage.Properties.Add(HttpPropertyKeys.IsLocalKey, (object) new Lazy<bool>((Func<bool>) (() => requestBase.IsLocal))); 
    httpRequestMessage.Properties.Add(HttpPropertyKeys.IncludeErrorDetailKey, (object) new Lazy<bool>((Func<bool>) (() => !httpContextBase.IsCustomErrorEnabled))); 
    return httpRequestMessage; 
} 

更新2:

在mvc控制器的內部,上下文是可用的。但不是在webapi控制器。

+0

您可以安全地刪除global.asax文件,以便在應用程序中只獲取一個入口點。我不確定這是否會解決問題,但它肯定會讓事情變得更清潔...... – 2014-10-20 12:51:31

+0

VS附帶的Web應用程序模板創建了global.asax和啓動類。有人說可以'保持',因爲它可以很容易地將事件掛鉤......我不確定它會幫助我刪除它,但會嘗試。 – Vegar 2014-10-20 16:45:23

回答

3

隊友找到了解決方案。他簡單地添加以下行至owin啓動類:

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 

爲什麼這樣可以解決問題是另一個謎,雖然。但我們正在使用wsFederation,所以我想這需要一些方法。但是如果我們不使用wsFed呢?我們是否仍然需要它來獲得上下文?誰知道......

+0

工程,但我真的很感激,如果有一天我明白了爲什麼...... – 2016-06-16 20:08:02