2013-11-26 37 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); –