从 Windows 服务调用表单身份验证站点中托管的 WCF 服务

Calling WCF service hosted in Forms Authentication site from a Windows Service

我们有一个 Windows 服务进程不断处理来自 微软消息队列。当根据这些消息采取行动时,它正在调用 来自 WCF 服务的方法。

该 WCF 服务托管在 ASP.net 网站中,该网站不仅具有 WCF 服务也是最终用户的前端。通常,WCF 方法是 修改内存中的数据结构,前端正在读取它们。这 数据不断被修改,需要通知客户变化 立即地。 (我们正在使用 SignalR。)

只要 ASP.net 站点使用 Windows,一切都很好 集成身份验证。现在要求前端使用Forms 验证。当然,这打破了 WCF 绑定。上一个绑定 是:

<basicHttpBinding>
  <binding name="BasicHttpBinding_ISessionWebService">
    <security mode="Transport">
      <transport clientCredentialType="Windows" />
    </security>
  </binding>
</basicHttpBinding>

前端用户不需要能够调用服务。 (其实他们 应该做不到。)

理想情况下,我希望 WCF 服务继续使用 Windows 身份验证和 站点的其余部分使用表单身份验证,但我认为 IIS 不支持 这个。我宁愿不必存储和传递帐户密码 运行 Windows 服务,但如果这是唯一的方式,我可以接受。我 在想可能有一些使用客户端证书的绑定,但我 我不确定如何设置。

如何以安全且可访问的方式公开 WCF 端点 从 Windows 服务调用?

AFAIK IIS 7 不允许这样做,解决方法似乎比只创建两个站点更粗略。

您可以在服务器上的单独 IIS 站点上分别创建两个服务。数据服务将使用 Windows Authentication 并保存数据结构。前端服务将使用 Forms Authentication 然后将请求重定向到数据服务。如果您想使用 ApplicationPool 标识排除其他网站,则可以为前端服务的应用程序池使用自定义标识。

这最终比我想象的要容易。秘方正在改变 绑定到 TransportWithMessageCredential.

的安全模式

来自"Programming WCF Security"

Transport security depends on the mechanism that the binding you have selected uses. For example, if you are using WSHttpBinding then the security mechanism is Secure Sockets Layer (SSL) (also the mechanism for the HTTPS protocol). Generally speaking, the main advantage of transport security is that it delivers good throughput no matter which transport you are using. However, it does have two limitations: The first is that the transport mechanism dictates the credential type used to authenticate a user....

TransportWithMessageCredential中,HTTPS仍然用于保护 传输消息,但您不必强制使用身份验证 传输机制的方案。所以 IIS 站点仍然可以使用 表单身份验证,但 WCF 消息使用 Windows 进行身份验证。这 绑定如下所示:

<wsHttpBinding>
  <binding name="WsHttpEndpoint">
    <security mode="TransportWithMessageCredential">
      <transport clientCredentialType="None" />
      <message clientCredentialType="Windows" />
    </security>
  </binding>
</wsHttpBinding>

从那里,您可以使用以下方法保护 WCF 服务的方法 PrincipalPermissionAttribute,即:

[PrincipalPermission(SecurityAction.Demand, Role = "DOMAIN\SomeGroup")]
public void DoWork()
{        
}