【问题标题】:Restrict WCF Web Service functionality based on User Group根据用户组限制 WCF Web 服务功能
【发布时间】:2009-08-27 18:43:54
【问题描述】:

我有一个由 C# 客户端应用程序使用的 WCF Web 服务。我还有 4 个组存储在 Active Directory 中。客户端应用程序正在传递用户凭据以连接此 Web 服务。

Web 服务公开多个 API 或方法供客户端应用程序访问,如下所示:

    [OperationContract]
    bool Read();


    [OperationContract]
    bool Write();

Read() 方法应该可供所有客户端访问

只有属于 Active Directory 维护的特定 windows 用户组的用户才能访问 Write() 方法。

问题: 我们如何根据客户端在AD中维护的用户组过滤或限制暴露的接口或方法?


jrista, 感谢您的回复。我尝试了与 PrincipalPermission 相同的指令,如下所示:

[PrincipalPermission(SecurityAction.Demand, Role = "Readers")]
[OperationContract]
bool Read();

[PrincipalPermission(SecurityAction.Demand, Role = "Writers")]
[OperationContract]
bool Write();

但它不起作用。读组用户也可以调用Writer()方法,写组用户也可以调用Write()方法。

我想告诉你的一件事是,我在 web.config 文件中使用了 BasicHttpBind,如下所示:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBind">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" proxyCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="DXDirectory.DXDirectoryService" behaviorConfiguration="DXDirectory.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBind"
                  name="BasicBinding" contract="DXDirectory.IDXDirectoryService">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DXDirectory.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceAuthorization principalPermissionMode="UseWindowsGroups"/>          
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

是否需要为此功能实现 wsHttpBinding?如果是,那么如何在我的 Web 服务中实现 wsHttpBinding?

【问题讨论】:

  • 如果您在 IIS 中托管,服务器是否设置为允许匿名?
  • 否,匿名未选中,集成 Windows 身份验证已选中。基本和摘要式身份验证未选中。
  • 我发现由于某种原因,WCF 无法识别合约接口上的声明性安全性,它必须在实际实现上。

标签: wcf service


【解决方案1】:

我不确定如何将 AD 凭据集成到正常的 .NET 安全框架中。但是,这是可能的(我会看看我是否能找到一些链接),一旦你这样做了,你应该能够使用标准安全属性来检查与你的 AD 组相对应的“角色”:

[OperationContract]
bool Read();

[PrincipalPermission(SecurityAction.Demand, Role = "Writers")]
[OperationContract]
bool Write();

要使用 AD 组,请配置服务行为:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <adServiceBehavior>
        <serviceAuthorization principalPermissionMode="UseWindowsGroups" />
      </adServiceBehavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

有另一个想法。有时甚至希望接口上根本没有 Write() 方法。使用 WCF,您可以在单个服务类上实现多个服务协定接口。一个理想的解决方案可能是创建两个服务契约接口,一个使用 Read() 和 Write(),一个只使用 Read()。根据登录到客户端的用户,您可以将 Read() 接口用于那些只有读取权限的用户,而将 Read()/Write() 接口用于那些同时具有访问权限的用户。这也将允许您向不应具有写访问权限的客户端公开最安全的服务合同,同时在内部使用读/写合同进行管理。您永远不会公开可能以这种方式被利用的代码。

【讨论】:

  • 谢谢 Marc,请看下面我的 cmets
【解决方案2】:

jrista 是对的 - 您可以使用内置的 Windows 授权服务,包括“PrincipalPermission”属性来限制访问。

但是:在您可以授权之前,您需要进行身份验证。首先,在决定是否让他(或她)进来之前,您需要知道谁在敲您的服务的门。

为此,您需要确保在消息交换中使用 Windows 凭据,并且客户端和服务器必须在同一个域中(或在具有相互信任关系的域中)。此外,您将需要使用默认情况下允许并支持 Windows 凭据的 wsHttp 或 netTcp 之类的绑定,并且您需要确保使用和配置将 Windows 凭据从客户端传输到服务器的绑定安全配置。

你需要有类似的东西:

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="Secured">
        <security mode="Transport">
          <transport clientCredentialType="Windows" />
        </security>
      </binding>
    </netTcpBinding>
  </bindings>
</system.serviceModel>

然后您需要从客户端和服务器端点引用该绑定配置。

WsHttpBinding 和 NetTcpBinding 都默认使用 Windows 客户端凭据,因此开箱即用,除非您完全关闭安全性,否则您应该在这两个绑定中获得 Windows 凭据支持。

马克

PS:
正如 jrista 所示(我在之前对 almost the same question 的回答中所做的那样),您实际上只需要将该 PrincipalPermission 属性添加到您希望限制属于某个组的用户的方法中 - 无需手动处理 AD需要组成员资格等。

如果您确实必须获取调用您的服务的用户所属的组,您可以查看 WindowsIdentity 调用的“.Groups”属性:

WindowsIdentity winCaller = ServiceSecurityContext.Current.WindowsIdentity;
foreach(var group in winCaller.Groups)
{
   Console.WriteLine(group.Value);
}

如果您需要呼入用户的姓名,请使用winCaller.Name。如果您需要用户呼叫的 SID,请使用 winCaller.User。一切都好 - 没有混乱,没有复杂的代码 - 只需使用它! :-)

【讨论】:

    【解决方案3】:

    尝试在服务类中的方法上添加Principalpermission属性,而不是在服务接口中的操作契约上。

    【讨论】:

      猜你喜欢
      • 2011-09-10
      • 2012-07-07
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多