2

我想迁移到 Windows Azure 云的现有 Web 应用程序在 (post)authenticaterequest 事件中以下列方式对用户进行身份验证:

IPrincipal current = Thread.CurrentPrincipal;
if (current != null && ((IClaimsIdentity)current.Identity).Claims.Count > 0)
{
    IPrincipal result =  AuthManager.CreateGenericPrincipal(current.Identity);
    HttpContext.Current.User = result;
    Thread.CurrentPrincipal = result;
}

CreateGenericPrincipal 方法在 xml 文件中查找 claimidentity 的角色,并使用该角色创建一个新的 GenericPrincipal。需要认证的页面只执行

IPrincipal p = Thread.CurrentPrincipal;
p.IsInRole("rolesFromXml");

这适用于一个 webrole 实例,因为与普通 IIS 托管没有太大区别。但它仍然适用于 2、3 或 5 个实例吗?Azure 负载均衡器不是“粘性的”,用户可以在使用应用程序时被转发到另一个实例。不知道 Thread.CurrentPrincipal 是否仍然是要走的路。

我在这里使用基于声明的身份。用户第一次进入页面时,他会被转发到安全令牌服务。到目前为止,这种情况只发生一次。如果在使用多个实例时多次发生这种情况会很烦人..

谢谢!

4

2 回答 2

2

通常发生的情况是您只被转发一次,重定向舞蹈(被动重定向)发生,并且您得到一个令牌。令牌通常以加密格式缓存在 cookie 中。因此,后续请求不会进行重定向舞蹈。

这里的挑战是,由于 cookie 是加密的,所以网络场中的所有服务器都必须具有加密密钥才能解密。开箱即用,您将遇到 WIF 问题,因为它默认为 DPAPI。这种类型的加密在每台机器上是故意不同的。这在云中中断。

您需要做的是上传服务证书作为部署的一部分,并将 cookie 的加密方式更改为对 webfarm 友好的内容。这是神奇的代码:

private void OnServiceConfigurationCreated(object sender, 
    ServiceConfigurationCreatedEventArgs e)
{
    var sessionTransforms =
        new List<CookieTransform>(
            new CookieTransform[] 
            {
                new DeflateCookieTransform(), 
                new RsaEncryptionCookieTransform(
                  e.ServiceConfiguration.ServiceCertificate),
                new RsaSignatureCookieTransform(
                  e.ServiceConfiguration.ServiceCertificate)  
            });
    var sessionHandler = new 
     SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
    e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(
        sessionHandler);
}

这会将您的安全令牌处理程序设置为将 RSA 加密与从已安装证书派生的密钥材料一起使用。

此示例应用程序中概述了更多详细信息和信息,用于说明问题和解决方案:

http://msdn.microsoft.com/en-us/library/ff966481.aspx

附加编辑:

ASP.NET 中有一个配置 WIF 的管道。它挂钩身份验证事件,并将从 cookie 中提取令牌并构建您的 IPrincipal,以便后续代码将其包含在上下文中。使用 STS 时,您通常不会自己构建 Principal。相反,如果您需要修改 Principal,您可以将插件插入 WIF 中的管道,并向“角色”声明(实际上是一个 URI 命名空间)插入其他声明。然后,WIF 将使用这些声明来构建 ClaimsPrincipal,该声明将包含诸如角色之类的内容,并且可以正常工作(IsInRole、web.config auth 等)。

如果可能,最好让令牌包含作为声明的角色。这是一个更长的讨论,但是围绕有意义的上下文的声明的“正常化”。请记住,您从 IP-STS 获得的声明是用他们自己的术语来说的,它们可能对您的应用程序没有任何意义。例如,我可能会收到客户声称他们是 Adatum\Managers 组的一部分。这对我的应用程序来说完全没有意义,所以我通常会将该令牌交换为我的应用程序理解的令牌,并在此过程中通过声明映射(即 Adatum\Managers --> MyApplicationAdminRole)转换或规范化声明。Windows Azure ACS 服务非常适用于帮助做到这一点(标准化来自不同 IP 的声明)。

我建议阅读Vittorio关于这一切的书,以了解这里的常见模式:

Eugenio 的笔记: 添加到 @dunnry 所写的内容,这都是正确的。在依赖方(您的 Web 应用程序)中增加您的声明集的适当扩展点是使用ClaimsAuthenticationManager。这种类型的文档在这里。该页面中有指向样本的指针。在该类中,您将从 XML 文件中读取角色并将它们添加到 ClaimsIdentity。该应用程序的其余部分不会担心索赔等(特别是如果您使用的是您的案例中的角色)。用于 cookie 加密的 RSA 配置解决了负载平衡器问题。

于 2011-10-25T15:06:18.607 回答
1

看我的帖子,我也是这么干的。

http://therubblecoder.wordpress.com/2011/10/25/wif-and-load-balancing-with-mvc-3/

基本上,声明令牌需要可用于任何集群节点,因此在 sessiontokenhandler 上使用证书将阻止特定节点以特定于实例的方式处理令牌。

在配置中的 microsoft.identity 元素中,您需要有一个看起来像这样的元素。

<serviceCertificate>
  <certificateReference x509FindType="FindByThumbprint"    findValue="****THUMBPRINT*****" storeLocation="LocalMachine"  storeName="My" />
</serviceCertificate>

应用程序池也需要访问它,否则它将无法通过指纹找到证书。

上面的代码在处理令牌时会使用这个证书。如果您没有此设置,您将获得空引用异常。

于 2011-10-25T14:16:39.570 回答