2013-11-26 42 views
3

我目前在我的MVC.NET應用程序中使用Windows Azure活動目錄作爲單一登錄,並且該部分效果很好。我可以通過WAAD進行身份驗證,並且無需任何問題即可加載我的ClaimsPrincipal。用Windows Azure Active Directory(WAAD)轉換聲明

下一步是通過添加來自不同數據源的新索賠來轉換從WAAD檢索到的索賠。就此而言,我創建了一個繼承ClaimsAuthenticationManager的類(見下文)。聲明被添加到委託人,並在CreateSession方法中持久化到會話cookie。

我現在的問題是,ClaimsPrincipal.Current不包含我添加的任何附加聲明。當我設置的SessionAuthenticationModule_SessionSecurityTokenReceived事件斷點,我可以看到,還有的ClaimsPrincipal.Current

ClaimsPrincipal.Current.FindAll(ClaimTypes.Email) 
Count = 0 

和e.SessionToken.ClaimsPrincipal之間的差異。

e.SessionToken.ClaimsPrincipal.FindAll(ClaimTypes.Email) 
Count = 1 
[0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: [email protected]} 

我在這裏錯過了什麼?在處理轉換聲明的所有示例中,我都沒有提到從Cookie手動重新加載ClaimsPrincipal。會話安全標記事件是否會重新加載ClaimsPrincipal或我打破安全模型?

謝謝。

public class MyAuthenticationManager : ClaimsAuthenticationManager 
{ 
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) 
    { 
     if (!incomingPrincipal.Identity.IsAuthenticated) 
     { 
      return base.Authenticate(resourceName, incomingPrincipal); 
     } 

     var transformedPrincipal = this.CreateUserPrincipal(incomingPrincipal.Identity.Name); 
     this.CreateSession(transformedPrincipal); 

     return transformedPrincipal; 
    } 

    private ClaimsPrincipal CreateUserPrincipal(String userName) 
    { 
     List<Claim> claims = new List<Claim>(); 
     var user = SecurityController.GetUserIdentity(userName); 

     claims.Add(new Claim(ClaimTypes.Name, userName)); 
     claims.Add(new Claim(ClaimTypes.Email, user.Email)); 
     claims.Add(new Claim(ClaimTypes.GivenName, user.FirstName)); 
     claims.Add(new Claim(ClaimTypes.Surname, user.LastName)); 

     return new ClaimsPrincipal(new ClaimsIdentity(claims, "MyCustom")); 
    } 

    private void CreateSession(ClaimsPrincipal transformedPrincipal) 
    { 
     var sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8)); 

     if (FederatedAuthentication.SessionAuthenticationModule != null && 
     FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(HttpContext.Current.Request.Cookies)) 
     { 
      return; 
     } 
     FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken); 
     //Added line below as per suggestion in one of the posts 
     //Doesn't seem to have any effect 
     Thread.CurrentPrincipal = transformedPrincipal; 
     FederatedAuthentication.SessionAuthenticationModule.SessionSecurityTokenReceived += SessionAuthenticationModule_SessionSecurityTokenReceived; 
    } 

    void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("SessionAuthenticationModule_SessionSecurityTokenReceived"); 
    } 
+0

在應用程序的.config文件中配置了MyAuthenticationManager嗎? – mcollier

+0

您的測試存在缺陷,因爲您嘗試使用字符串「電子郵件」查找聲明,因此它應該是ClaimTypes.Email或「http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress 「 – Rob

+0

是的,MyAuthenticationManager是在.config文件中配置的。 Authenticate方法被調用,我可以通過它。 –

回答

2

看起來我必須通過ClaimsIdentity而不是ClaimsPrincipal訪問聲明。現在我可以在我的應用程序中成功訪問任何視圖或控制器中的聲明。在AuthenticationManager會

((ClaimsIdentity)Thread.CurrentPrincipal.Identity).FindAll(ClaimTypes.Email) 
Count = 1 
    [0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: [email protected]} 

最終代碼庫看起來是這樣的(注意,沒有明確的賦值操作的ClaimsPrincipal在當前線程)。

public class MyAuthenticationManager : ClaimsAuthenticationManager 
{ 
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) 
    { 
     if (!incomingPrincipal.Identity.IsAuthenticated) 
     { 
      return base.Authenticate(resourceName, incomingPrincipal); 
     } 

     var transformedPrincipal = this.CreateUserPrincipal(incomingPrincipal.Identity.Name); 
     this.CreateSession(transformedPrincipal); 

     return transformedPrincipal; 
    } 

    private ClaimsPrincipal CreateUserPrincipal(String userName) 
    { 
     List<Claim> claims = new List<Claim>(); 
     var user = SecurityController.GetUserIdentity(userName); 

     claims.Add(new Claim(ClaimTypes.Name, userName)); 
     claims.Add(new Claim("UserId", user.Id.ToString())); 
     claims.Add(new Claim(ClaimTypes.Email, user.Email)); 
     claims.Add(new Claim(ClaimTypes.GivenName, user.FirstName)); 
     claims.Add(new Claim(ClaimTypes.Surname, user.LastName)); 
     //claims.Add(new Claim(ClaimTypes.NameIdentifier, userName)); 

     if (user.Account != null) 
     { 
      claims.Add(new Claim("AccountId", user.Account.Id.ToString())); 
      claims.Add(new Claim("AccountName", user.Account.Name.ToString())); 
     } 
     if (user.Owner != null) 
     { 
      claims.Add(new Claim("OwnerId", user.Owner.Id.ToString())); 
      claims.Add(new Claim("OwnerName", user.Owner.Name.ToString())); 
     } 

     return new ClaimsPrincipal(new ClaimsIdentity(claims, "MyCustom")); 
    } 

    private void CreateSession(ClaimsPrincipal transformedPrincipal) 
    { 
     if (FederatedAuthentication.SessionAuthenticationModule != null && 
     FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(HttpContext.Current.Request.Cookies)) 
     { 
      return; 
     } 
     var sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8)); 
     FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken); 
    } 
} 
0

我沒有看到您將您的ClaimsPrincipal(轉換後)添加回Thread.CurrentPrincipal。請嘗試

private void CreateSession(ClaimsPrincipal transformedPrincipal) 
    { 
     var sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8)); 

     if (FederatedAuthentication.SessionAuthenticationModule != null && 
     FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(HttpContext.Current.Request.Cookies)) 
     { 
      return; 
     } 
     FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken); 
     //Following is the missing line of code. 
     Thread.CurrentPrincipal = transformedPrincipal; 
    } 
+0

我將主體分配給CurrentPrincipal,但沒有任何效果。我將再次嘗試在文章之後建立一個單獨的POC解決方案。 –

+0

是否確定寫入Cookie,並且代碼未從以下代碼返回FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(HttpContext.Current.Request.Cookies)) { return; } –

+0

也可以嘗試使用以下SessionAuthenticationModule編寫cookie sam = FederatedAuthentication.SessionAuthenticationModule; var st = sam.CreateSessionSecurityToken(transformedPrincipal,null,validFrom,validTo,isPersistantCookie); sam.WriteSessionTokenToCookie(st); –