ASP.NET调用WCF服务时的身份验证/模拟问题

时间:2010-11-03 14:12:14

标签: asp.net wcf authentication

我有一个调用WCF服务的网页,该服务使用Integrated Security进行sql数据库调用。我收到一条错误消息,“用户'CorpDomain \ ServerName01 $'登录失败”。我想要它,以便所有层都将在用户的AD凭证(在Intranet中工作)下执行,即:“CorpDomain \ Albert”。

在服务器(Win 2008 / IIS 7)上,我打开了Windows身份验证,并在身份验证下为Web客户端和WCF服务关闭了其他所有内容(包括Anonymous)。

这是我的客户端web.config:

<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0"/>
        <authentication mode="Windows"/>
        <identity impersonate="true"/>
        <customErrors mode="Off"/>
    </system.web>
    <system.serviceModel>
   <bindings>
     <netTcpBinding>
       <binding name="NetTcpBinding_IMyService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
         <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
         <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
         <!--<security mode="Transport">
           <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
           <message clientCredentialType="Windows" />
         </security>-->
      </binding>
    </netTcpBinding>
  </bindings>
  <client>
   <endpoint address="net.tcp://myurladdress/MyServices/Service.svc"
    binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMyService"
    contract="MySvc.IMyService" name="NetTcpBinding_IMyService" />
  </client>
  <behaviors>
    <endpointBehaviors>
      <behavior name="ClientUserNameBehavior">
        <clientCredentials>
          <windows allowedImpersonationLevel="Impersonation"/>
        </clientCredentials>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

这是我的WCF服务web.config:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <authentication mode="Windows"/>
    <identity impersonate="true"/>
  </system.web>
  <connectionStrings>
    <!--DB CONNECTION-->
    <add name="myDB" connectionString="Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Carbon;Data Source=mydbname,10600" providerName="System.Data.SqlClient"/>
  </connectionStrings>

  <system.serviceModel>
    <services>
      <service name="WCFServices.MyService" behaviorConfiguration="MyServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8000/WCFServices/MyService"/>
          </baseAddresses>
        </host>
        <endpoint address="" binding="netTcpBinding" contract="WCFServices.IMyService" bindingConfiguration="tcpWindowsSecurity" bindingNamespace="http://WCFServices.MySvc/"/>
        <endpoint address="MEX" binding="mexTcpBinding" contract="IMetadataExchange"/>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceBehavior">
          <serviceMetadata httpGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceAuthorization impersonateCallerForAllOperations="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="tcpWindowsSecurity" maxReceivedMessageSize="524288" maxBufferSize="524288">
          <!--<security mode="TransportWithMessageCredential">
            <transport clientCredentialType="Windows" protectionLevel="None" />
          </security>-->
        </binding>
      </netTcpBinding>
    </bindings>

    <!--<serviceHostingEnvironment multipleSiteBindingsEnabled="true" >-->
    <serviceHostingEnvironment >
      <serviceActivations>
        <add relativeAddress="~/MyService.svc" service="WCFServices.MyService"/>
      </serviceActivations>
    </serviceHostingEnvironment>

  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>
客户端

Request.ServerVariables [“AUTH_USER”]。ToString()=“CorpDomain \ Albert”

Page.User.Identity.Name =“CorpDomain \ Albert”

System.Threading.Thread.CurrentPrincipal.Identity.Name =“CorpDomain \ Albert”

System.Security.Principal.WindowsIdentity.GetCurrent()。Name =“NT AUTHORITY \ NETWORK SERVICE”

我的客户端代码基本上是:

MySvc.MyServiceClient svc = new MySvc.MyServiceClient();
svc.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
Response.Write(svc.GetServiceHtml());

并在 WCF方面

ServiceSecurityContext.Current.WindowsIdentity.Name =“NT AUTHORITY \ NETWORK SERVICE”

服务器端代码是:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetServcieHtml()
{
    string name, link;
    StringBuilder html = new StringBuilder();

    html.Append(ServiceSecurityContext.Current.WindowsIdentity.Name);

    try
    {

        using (SqlConnection conn = GetDataConnection())
        {
            conn.Open();
            SqlCommand sqlcom = new SqlCommand("dbo.runsomeproc", conn);
            sqlcom.CommandType = CommandType.StoredProcedure;
            SqlDataReader sqlDataReader = sqlcom.ExecuteReader();


            while (sqlDataReader.Read())
            {
                // ** SOME CODE HERE **
            }

            conn.Close();
        }
    }
    catch (Exception ex)
    {
        html.AppendLine("<br><br>ERROR:" + ex.Message + " " + ex.InnerException);
        return html.ToString();
    }
    return html.ToString();
}

注意: 我得到的错误是:错误:用户'CorpDomain \ ServerName01 $'登录失败。

知道我做错了吗?

3 个答案:

答案 0 :(得分:0)

您还需要在WCF服务级别启用模拟。

MSDN page包含所有详细信息。

答案 1 :(得分:0)

我不知道这是否会对任何人有所帮助,但我遇到了这个问题。问题是由于我的服务在IIS中使用的应用程序池的标识设置。如果你在那里设置了适当的身份,你应该是好的。在我的例子中,默认设置为NT Authority \ Network Service。

答案 2 :(得分:0)

另外,如果我错了,请更正我,但在您的客户端web.config中,您有一种行为会将模拟级别设置为“模拟”,但您不会在端点中引用该行为。例如:

  <client>
   <endpoint address="net.tcp://myurladdress/MyServices/Service.svc"
    binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMyService"
    contract="MySvc.IMyService" name="NetTcpBinding_IMyService" />
  </client>

应该是:

  <client>
   <endpoint address="net.tcp://myurladdress/MyServices/Service.svc"
    binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMyService"
    contract="MySvc.IMyService" name="NetTcpBinding_IMyService"
    behaviorConfiguration="ClientUserNameBehavior" />
  </client>