2012-10-31 94 views
2

我有一個FubuMvc網站,它使用來自WIF單點登錄服務器的基於聲明的授權。身份驗證發生在SSO上,包括角色和一組自定義聲明的聲明被傳遞到網站以進行授權。根據索賠允許或拒絕訪問整個站點

SSO和網站正常工作,但基於角色的授權,但我想要做的是拒絕訪問整個網站保存錯誤頁面的基礎上沒有自定義聲明。目前我正在使用自定義ClaimsAuthenticationManager,它檢查索賠並檢查是否存在所需索賠。如果聲明丟失,則會引發異常。這會導致500錯誤,但我真正想要的是系統拋出401錯誤並重定向到網站上的未授權頁面。

以下是自定義ClaimsAuthenticationManager的示例。

public class CustomAuthenticationManager : ClaimsAuthenticationManager 
{ 
    private readonly string expectedClaim; 

    public CustomAuthenticationManager (object config) 
    { 
     var nodes = config as XmlNodeList; 
     foreach (XmlNode node in nodes) 
     { 
      using (var stringReader = new StringReader(node.OuterXml)) 
      using (var rdr = new XmlTextReader(stringReader)) 
      { 
       rdr.MoveToContent(); 
       rdr.Read(); 
       string claimType = rdr.GetAttribute("claimType"); 
       if (claimType.CompareTo(ClaimTypes.CustomClaim) != 0) 
       { 
        throw new NotSupportedException("Only custom claims are supported"); 
       } 
       expectedSystemName = rdr.GetAttribute("customClaimValue"); 
      } 
     } 
    } 

    public override IClaimsPrincipal Authenticate(
     string resourceName, IClaimsPrincipal incomingPrincipal) 
    { 
     var authenticatedIdentities = incomingPrincipal.Identities.Where(x => x.IsAuthenticated); 
     if (authenticatedIdentities.Any() && 
       authenticatedIdentities.Where(x => x.IsAuthenticated) 
             .SelectMany(x => x.Claims) 
             .Where(x => x.ClaimType == ClaimTypes.CustomClaim) 
             .All(x => x.Value != expectedClaim)) 
     { 
       throw new HttpException(
        (int)HttpStatusCode.Unauthorized, 
        "User does not have access to the system"); 
     } 
     return base.Authenticate(resourceName, incomingPrincipal); 
    } 
} 

上述工作,並阻止對系統的訪問,但TI並不十分友好的使用,因爲用戶只是得到一個500錯誤。此外,因爲用戶基本上登錄了他們但沒有訪問權限,他們無法註銷。我公開了一個未經授權的錯誤頁面,該頁面提供對匿名用戶的訪問,但我無法重定向用戶。

回答

4

我想知道爲什麼你在認證管理器中實現了你的邏輯。

你有沒有考慮切換到ClaimsAuthorizationManager?對於這個工作,你需要將ClaimsAuthorizationModule添加到您的管道:

<system.webServer> 
    <modules> 
     ... 
     <add name="SessionAuthenticationModule" .... 
     <add name="ClaimsAuthorizationModule" type="Microsoft.IndentityModel.Web.ClaimsAuthorizationModule, Microsoft.IndentityModel.Web" /> 
    </modules> 
</system.webServer> 

然後創建您的授權角色的結構:

<claimsAuthorizationManager type="yourtype, yourassembly"> 
     <requiredClaim claimType="foobar" /> 
</claimsAuthorizationManager> 

,並在經理:

public class FederatedClaimsAuthorizationManager : ClaimsAuthorizationManager 
{ 
    private List<string> _requiredClaims = new List<string>(); 

    public FederatedClaimsAuthorizationManager(object config) 
    { 
     XmlNodeList nodes = config as XmlNodeList; 
     foreach (XmlNode node in nodes) 
     { 
      XmlTextReader xtr = new XmlTextReader(new StringReader(node.OuterXml)); 
      xtr.MoveToContent(); 

      _requiredClaims.Add(xtr.GetAttribute("claimType")); 
     } 
    } 

    public override bool CheckAccess(AuthorizationContext context) 
    { 
     IClaimsIdentity identity = context.Principal.Identities[0]; 

     return !identity.IsAuthenticated || 
       identity.Claims.Any(c => _requiredClaims.Any(rq => c.ClaimType == rq)); 
    } 
} 

這與你的方法之間的區別在於,失敗的授權是通過重新激活驗證過程來處理的 - 沒有例外,沒有500秒。

例如 - 如果您在登錄頁面上使用<wif:FederatedPassiveSignIn />,那麼失敗的授權只是將用戶重定向到登錄頁面,您可以檢查用戶是否已通過身份驗證,並顯示「您已被重定向到登錄頁面可能意味着您試圖訪問您無權訪問的資源「。

+0

我已經驗證過該答案是正確的。授權必須在'ClaimsAuthorizationManager'中完成。從'CheckAccess'返回'false'是獲得401響應的唯一方法。 –

1

除了轉換聲明的典型情況之外,文檔不清楚如何實現身份驗證。如果您需要根據索賠拒絕用戶,那麼您就是您自己的。

我已經嘗試返回null並拋出各種異常,包括401(類似於你的例子)。我發現最好的解決方案是創建並返回一個匿名主體。

using System.Security.Principal; 

... 

public class CustomAuthenticationManager : ClaimsAuthenticationManager 
{ 
    public override IClaimsPrincipal Authenticate(
     string resourceName, 
     IClaimsPrincipal incomingPrincipal) 
    { 
     ... 

     ClaimsIdentity identity = new GenericIdentity(String.Empty); 
     return new GenericPrincipal(identity, new string[0] { }); 
    } 
} 

您必須傳遞一個空字符串作爲標識名,以便對通用聲明標識上的IsAuthenticated返回false。

相關問題