在WCF中获取调用者用户名而不是计算机名

时间:2016-08-25 11:30:44

标签: c# asp.net-mvc wcf iis-8

我有一个ASP.NET MVC WebApplication,托管在server-frontend,它是server-wcf中托管的WCF应用程序的客户端,两者都在同一个网络/域中。两台服务器都是运行IIS 8的Windows Server 2012。

我在两个项目中启用了Windows身份验证并禁用了匿名(csproj)。

如果我在我的WebApp中的控制器中调用this.User.Identity.Name,它会正确地提供登录的用户(例如mydomain \ alisson)。

两个项目都在IIS中配置了Windows身份验证,而WebApp特别启用了ASP.NET模拟。两者都禁用表单,基本和匿名。两个池都使用NetworkService

我的WCF项目负责连接到SQL Server,并且它正常工作,因为我在我的数据库中授予了机器本身的权限(例如server-wcf$),这正是我所期望的。

现在我正试图从我的WebApp中调用WCF方法,如下所示:

var binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = 10485760;
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

var endPoint = new EndpointAddress(address);
var channelFactory = new ChannelFactory<IMyService>(binding, endPoint);
var client = channelFactory.CreateChannel();
client.GetUser();

并且我的WCF服务中的GetUser()声明如下:

public GetUser()
{
    return ServiceSecurityContext.Current.WindowsIdentity.Name;
}

返回domain\server-frontend而不是domain\alisson

我想让它在WCF中获取用户,但保持WCF连接数据库的方式(server-wcf)。

我的WebApp web.config具有以下内容:

<identity impersonate="true" />
<authentication mode="Windows" />
<authorization>
  <deny users="?" />
</authorization>

而WCF在web.config serviceModel中包含以下内容:

<bindings>
  <basicHttpBinding>
    <binding name="AutomatizacaoBinding" maxReceivedMessageSize="10485760">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Windows" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<protocolMapping>
  <add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

有可能实现这个目标吗?

2 个答案:

答案 0 :(得分:0)

您应该使用OperationContext代替:

return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;

注意:如果未启用集成安全性,ServiceSecurityContext将为空。

希望它有所帮助。

答案 1 :(得分:0)

很可能但不那么容易。

您可能只能获取调用者的名称,但不能重建他们的身份。永远,在重建身份时,必须在机器之间使用Negotiate / Kerberos Security for more than one jump

基本上真的很无聊,因为并不总是有可用于测试的Active Directory服务器(我必须在我所在的生产环境中创建测试帐户)。 Neg / Kerberos是我大部分时间都使用的老技术,尽管有一些关于SPN和CNAME的警告(不要使用CNAMES,使用A记录)。

另一种选择是使用像ADFS这样的新技术来传递某种叫做联邦的大型声明cookie,但这完全取决于你的生产环境是什么样的。

一旦设置了这个,一个或另一个,如果你希望WCF继续自己进行调用,只需保留你的代码并且不要设置任何隐式模拟。如果你在大多数情况下在wcf请求中逛了,你仍然可以获得身份。

如果您想实际模拟,请打开impersonation scope。只要重复一下这个例子,除非先设置Kerberos或adfs,否则以下内容永远不会有效。

using System.Security.Principal;
using(WindowsIdentity.GetCurrent().Impersonate())
{
     //your code goes here, executed as domain\alisson
}