Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将WindowsIdentity转换为NetworkCredential?_C#_.net - Fatal编程技术网

C# 如何将WindowsIdentity转换为NetworkCredential?

C# 如何将WindowsIdentity转换为NetworkCredential?,c#,.net,C#,.net,如何将WindowsIdentity转换为NetworkCredential?我正在测试我的WCF服务,以验证匿名呼叫者是否被阻止。要做到这一点,我想做如下工作: myProxy.ClientCredentials.Windows.ClientCredential = foo(WindowsIdentity.GetAnonymous()); 其中foo是一种将WindowsIdentity转换为NetworkCredential的方法,一般来说,foo不存在。因为NetworkCredenti

如何将
WindowsIdentity
转换为
NetworkCredential
?我正在测试我的WCF服务,以验证匿名呼叫者是否被阻止。要做到这一点,我想做如下工作:

myProxy.ClientCredentials.Windows.ClientCredential = foo(WindowsIdentity.GetAnonymous());

其中
foo
是一种将
WindowsIdentity
转换为
NetworkCredential

的方法,一般来说,foo不存在。因为NetworkCredential是一个更广泛的对象,它支持WindowsIdentity。也就是说,我可以在需要WindowsIdentity的地方使用NetworkCredential,但不能反过来使用

原因是出于安全考虑

NetworkCredential表示允许您使用此标识并在另一台计算机上使用其关联的凭据

这意味着

  • 您拥有用户凭据,而不仅仅是其标识
  • 这组凭据适用于模拟,而不仅仅是本地访问
  • 我将假定凭据来自另一台机器(由于WCF)。同样出于安全原因,当跨越到这台机器上时,该网络凭据已转换为LocalCredential(除非我们讨论的是委派而不是模拟)。客户端计算机授予了在服务器计算机上使用其凭据的权限,并且仅在服务器计算机上使用

    如果您想恢复NetworkCredential,您需要执行一项称为委派的操作,因为这就是所谓的多跳问题。这涉及到Kerberos,一只黑社会的三头恶狗。您不想处理Kerberos

    一般来说,默认情况下,WCF代理不会在调用时发送凭据。通常需要设置ClientCredentials或

    proxy.UseDefaultCredentials = true
    

    不提供这两个选项通常意味着没有凭据,因此没有匿名身份验证。

    我们有一组测试来执行此操作,并使用此帮助器方法:

    public static ResponseType CallService(RequestType requestBody, NetworkCredential credential)
    {
        ResponseType response;
        using (var channelFactory = new ChannelFactory<IMyService>("BasicHttpBinding_IMyService"))
        {
            channelFactory.Credentials.Windows.ClientCredential = credential;
    
            var client = channelFactory.CreateChannel();
            var request = new MyRequest()
                {
                    MyService = requestBody
                };
            response = client.MyService(request).MyResponse1;
            ((IClientChannel)client).Close();
    
            channelFactory.Close();
        }
        return response;
    }
    

    回答我自己的问题:
    无法将
    WindowsIdentity
    转换为
    NetworkCredential
    。若要测试匿名调用方是否被阻止,请使用模拟线程模拟当前线程,然后调用WCF服务。注意:请勿使用。这个方法是无用的(估计它被错误地实现了,并且从未被纠正)。使用空会话令牌模拟当前线程的代码(未执行错误处理):

    输出:

    my machine\me True NTLM
    NT AUTHORITY\ANONYMOUS LOGON False
    
    using mymachine\me True Negotiate
    mymachine\me,True,Negotiate
    
    setting svc.ClientCredentials.Windows.ClientCredential to null...
    mymachine\me,True,Negotiate
    
    using NT AUTHORITY\ANONYMOUS LOGON False
    The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be
     used for communication because it is in the Faulted state.
    
    Server stack trace:
       at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
    
    Exception rethrown at [0]:
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage req
    Msg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgDa
    ta, Int32 type)
       at System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
       at System.ServiceModel.ClientBase`1.System.ServiceModel.ICommunicationObject.
    Close(TimeSpan timeout)
       at System.ServiceModel.ClientBase`1.Close()
       at System.ServiceModel.ClientBase`1.System.IDisposable.Dispose()
       at TestClient.Program.MakeRequest()
    
    作为对Edmund评论的回应,将
    proxy.ClientCredentials.Windows.ClientCredential
    设置为
    null
    不会执行预期操作-以匿名用户身份发出请求。以下是我的完整测试代码及其输出:

    服务代码:

    public class Service1 : IService1
        {
            // note that if client is not authenticated, this code will never get a chance to execute
            // exception will happen before that
            // therefore there is no need to decorate this method with a
            // [PrincipalPermission(SecurityAction.Demand, Authenticated=true)] attribute        
            public string GetData()
            {
                try
                {
                    var identity = Thread.CurrentPrincipal.Identity;
                    return string.Concat(identity.Name, ",", identity.IsAuthenticated, ",", identity.AuthenticationType);
                }
                catch (Exception e)
                {
                    return string.Concat(e.Message, "\\r\\n", e.StackTrace);
                }
            }
        }
    
    服务配置:

    <services>      
          <service name="WcfService1.Service1">
            <host>
              <baseAddresses>
                <add baseAddress="http://mymachine/Service1/" />            
              </baseAddresses>                    
            </host>
            <endpoint address="Service1"
                      binding ="customBinding"
                      bindingConfiguration="myHttpBinding"
                      contract="WcfService1.IService1">          
            </endpoint>          
          </service>
        </services>
        <bindings>      
          <customBinding>
            <binding name="myHttpBinding">
                <reliableSession/>          
                <binaryMessageEncoding />          
                <httpTransport maxBufferSize="2147483647"
                               maxReceivedMessageSize="2147483647"
                               authenticationScheme="IntegratedWindowsAuthentication" />
              </binding>
          </customBinding>
        </bindings>
    
    客户端配置:

    <bindings>
                <customBinding>
                    <binding name="CustomBinding_IService1">
                        <reliableSession />
                        <binaryMessageEncoding />
                        <httpTransport authenticationScheme="Negotiate" />
                    </binding>
                </customBinding>
            </bindings>
            <client>
                <endpoint address="mymachine/Service1/Service1.svc/Service1"
                    binding="customBinding" bindingConfiguration="CustomBinding_IService1"
                    contract="ServiceReference1.IService1" name="CustomBinding_IService1">
                    <identity>
                        <servicePrincipalName value="host/mymachine" />
                    </identity>
                </endpoint>
            </client>
          <behaviors>
            <endpointBehaviors>
              <!-- this setting protects the client by prohibiting the service to assume identity of client
              via imperonation and/or delegation and then doing bad things -->
              <behavior name="ImpersonationBehavior">
                <clientCredentials>
                  <windows allowedImpersonationLevel="Identification"/>
                </clientCredentials>
              </behavior>
            </endpointBehaviors>
          </behaviors>
    

    这个答案似乎会回答你的问题:不,不会。首先,WindowsIdentity.GetAnonymous().Impersonate()给出了一个异常。这也记录在。InvalidOperationException尝试执行模拟的匿名身份。看起来没有办法去做问题中提出的事情。那么,如何测试服务不允许匿名用户进入呢?您的问题标题是在将WindowsIdentity转换为NetworkCredential之后,但在多次重新阅读您的问题之后,您只需要获得“匿名”用户就可以了?将客户机凭据设置为null将实现此目的,并将发布一些code@EdmundYeung99,将客户端凭据设置为null将不起作用。你可以自己试试。好的,但这对我们来说确实有效。很好,你找到了答案:)我也这么做了。使用这个我验证了WCF服务(或者更确切地说是IIS)不会让密码错误的用户通过。但我想测试匿名用户是否通过。当您将null传递到客户端凭据时,可以测试匿名用户
    static void MakeRequest()
            {
                try
                {
                    using (var svc = new Service1Client())
                    {
                        Console.WriteLine(svc.GetData());
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    Console.WriteLine(e.StackTrace);
                }
            }
    
            static void Test3()
            {            
                Console.WriteLine("using {0}", ToString(WindowsIdentity.GetCurrent()));
                MakeRequest();
                Console.WriteLine();
    
                Console.WriteLine("setting svc.ClientCredentials.Windows.ClientCredential to null...");
                try
                {
                    using (var svc = new Service1Client())
                    {
                        svc.ClientCredentials.Windows.ClientCredential = null; 
                        Console.WriteLine(svc.GetData());
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    Console.WriteLine(e.StackTrace);
                }
                Console.WriteLine();
    
                ImpersonateAnonymousUser();
                Console.WriteLine("using {0}", ToString(WindowsIdentity.GetCurrent()));
                MakeRequest();
                Console.WriteLine();
            }
    
    <bindings>
                <customBinding>
                    <binding name="CustomBinding_IService1">
                        <reliableSession />
                        <binaryMessageEncoding />
                        <httpTransport authenticationScheme="Negotiate" />
                    </binding>
                </customBinding>
            </bindings>
            <client>
                <endpoint address="mymachine/Service1/Service1.svc/Service1"
                    binding="customBinding" bindingConfiguration="CustomBinding_IService1"
                    contract="ServiceReference1.IService1" name="CustomBinding_IService1">
                    <identity>
                        <servicePrincipalName value="host/mymachine" />
                    </identity>
                </endpoint>
            </client>
          <behaviors>
            <endpointBehaviors>
              <!-- this setting protects the client by prohibiting the service to assume identity of client
              via imperonation and/or delegation and then doing bad things -->
              <behavior name="ImpersonationBehavior">
                <clientCredentials>
                  <windows allowedImpersonationLevel="Identification"/>
                </clientCredentials>
              </behavior>
            </endpointBehaviors>
          </behaviors>
    
    using mymachine\me True Negotiate
    mymachine\me,True,Negotiate
    
    setting svc.ClientCredentials.Windows.ClientCredential to null...
    mymachine\me,True,Negotiate
    
    using NT AUTHORITY\ANONYMOUS LOGON False
    The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be
     used for communication because it is in the Faulted state.
    
    Server stack trace:
       at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
    
    Exception rethrown at [0]:
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage req
    Msg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgDa
    ta, Int32 type)
       at System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
       at System.ServiceModel.ClientBase`1.System.ServiceModel.ICommunicationObject.
    Close(TimeSpan timeout)
       at System.ServiceModel.ClientBase`1.Close()
       at System.ServiceModel.ClientBase`1.System.IDisposable.Dispose()
       at TestClient.Program.MakeRequest()