52

在Web API項目中,我重寫了正常的身份驗證過程來檢查令牌。該代碼看起來是這樣的:爲什麼我的ClaimsIdentity始終是false(對於web api授權過濾器)?

if (true) // validate the token or whatever here 
{ 
    var claims = new List<Claim>(); 
    claims.Add(new Claim(ClaimTypes.Name, "MyUser")); 
    claims.Add(new Claim(ClaimTypes.NameIdentifier, "MyUserID")); 
    claims.Add(new Claim(ClaimTypes.Role, "MyRole")); 

    var claimsIdentity = new ClaimsIdentity(claims); 

    var principal = new ClaimsPrincipal(new[] { claimsIdentity }); 
    Thread.CurrentPrincipal = principal; 
    HttpContext.Current.User = principal; 
} 

再後來當我申請了[Authorize]屬性控制器,它未能批准。

調試代碼,證實了相同的行爲:

// ALWAYS FALSE! 
if (HttpContext.Current.User.Identity.IsAuthenticated) { 
    // do something 
} 

爲什麼它認爲用戶沒有通過驗證,即使我已經構造一個有效的ClaimsIdentity並將其分配給線程?

回答

109

問題是因爲.Net 4.5中發生了重大變化。正如this article所解釋的那樣,簡單地構造聲明標識不再使其IsAuthenticated返回true。相反,你需要傳遞一些字符串(無所謂)到構造函數中。

所以這條線在上面的代碼:

var claimsIdentity = new ClaimsIdentity(claims); 

變爲這樣:

// exact string doesn't matter 
var claimsIdentity = new ClaimsIdentity(claims, "CustomApiKeyAuth"); 

而問題就解決了。 更新:查看來自Leo的其他答案。確切的AuthenticationType值可能也可能不重要,具體取決於您在auth管道中還有哪些內容。

更新2:正如Robin van der Knaap在評論中所建議的那樣,System.Security.Claims.AuthenticationTypes值之一可能是合適的。

var claimsIdentity = new ClaimsIdentity(claims, AuthenticationTypes.Password); 

// and elsewhere in your application... 
if (User.Identity.AuthenticationType == AuthenticationTypes.Password) { 
    // ... 
} 
+8

儘管您可以添加任何字符串,但根據MSDN通常應該是AuthenticationTypes類中定義的值之一。 http://msdn.microsoft.com/zh-cn/library/system.security.claims.claimsidentity.authenticationtype(v=vs.110).aspx –

+1

示例:var claimsIdentity = new ClaimsIdentity(claims,AuthenticationTypes.Password); –

+2

字符串的值在User.Identity.AuthenticationType –

10

雖然提供的答案在其中有一定的有效性,但並不完全正確。你不能認爲只是添加任何字符串將神奇地工作。正如評論之一表示,該字符串必須然而匹配AuthenticationTypes枚舉而這又必須例如在OWIN認證/授權中間件中指定的匹配....之一...

public void ConfigureOAuth(IAppBuilder app) 
     { 
      app.UseCors(CorsOptions.AllowAll); 

      OAuthAuthorizationServerOptions serverOptions = new OAuthAuthorizationServerOptions() 
      { 
       AllowInsecureHttp = true, 
       TokenEndpointPath = new Microsoft.Owin.PathString("/token"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
       AuthenticationType = AuthenticationTypes.Password, 
       AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active, 
       Provider = new AppAuthServerProvider() 
      }; 


      app.UseOAuthAuthorizationServer(serverOptions); 
      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions() 
       { 
        AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active, 
        AuthenticationType = AuthenticationTypes.Password 
       });    
     } 

,在上述情況下,這並不重要。但是,如果你正在使用多個身份驗證/授權級別的索賠將關聯到同一AuthenticationType相匹配的一個...另一個例子是,當您使用cookie認證...

public void Configuration(IAppBuilder app) 
     { 
      app.UseCookieAuthentication(new CookieAuthenticationOptions 
      { 
       AuthenticationType = "ApplicationCookie", 
       LoginPath = new PathString("/auth/login") 
      }); 
     } 

其中AuthenticationType描述名稱的Cookie,因爲您的應用可能從其他提供商獲得了其他Cookie,因此設置AuthenticationType是非常重要的,以便實例化聲明以便與正確的Cookie相關聯

+0

在.NET Core中,您可以使用常量作爲AuthenticationType,例如[CookieAuthenticationDefaults.AuthenticationScheme](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.cookies.cookieauthenticationdefaults.authenticationscheme)或[JwtBearerDefaults.AuthenticationScheme](https://docs.microsoft .COM/EN-US/DOTNET/API/microsoft.aspnetcore.authentication.jwtbearer.jwtbearerdefaults.authenticationscheme)。 –

相關問題