C#在Win表单和Win服务之间传递凭据的正确方法

时间:2013-10-24 14:34:08

标签: c# winforms windows-services

我是C#的新手,所以请保持温和:)

我想要完成的是创建一个应用程序,以便这里的某个团队能够修改某些DNS条目。出于安全原因,我们无法为其Active Directory用户帐户授予对DNS的访问权限,我们正在尝试远离更改DNS条目,因为它耗费了大量时间。

所以我创建了一个Windows服务,其中包含几种获取和修改DNS条目的方法,以及一个使用Windows服务方法的Windows窗体。目的是让Windows服务在Active Directory用户帐户(服务帐户)下运行,该帐户具有对DNS的修改访问权限,并使Windows窗体在其普通用户帐户下运行。

如果我将表单作为我的管理员帐户(具有对DNS的修改权限)运行,一切正常,但是当我在我的普通用户帐户(没有对DNS的修改权限)下运行表单时,我得到了例外,

System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
   at System.Management.ManagementScope.InitializeGuts(Object o)
   at System.Management.ManagementScope.Initialize()
   at System.Management.ManagementObjectSearcher.Initialize()
   at System.Management.ManagementObjectSearcher.Get()
   at ChangeDNS.ChangeDNSService.getCName(String cName) in C:\Tools\Projects\ChangeDNSService\ChangeDNSService\Program.cs:line 58

我无法找到引用或示例来解释我所缺少的内容以及在表单和Windows服务之间传递凭据的正确方法。能否帮助我指出正确的方向,因为我们将非常感激。

谢谢和问候,

达里安

编辑:

表格包含以下代码,

ServiceReference1.ChangeDNSClient dnsClient = new ServiceReference1.ChangeDNSClient();
            dnsClient.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

Console.WriteLine(dnsClient.getCName("TestDarianCName1"));

服务具有以下代码,

public string getCName(string cName)
{
    serviceLog.Source = serviceName;
        string returnServer = "";

    try
        {
            ConnectionOptions connection = new ConnectionOptions();

        ManagementScope oMs = new ManagementScope("\\\\" + dnsServer + "\\root \\microsoftdns", connection);
                string strQuery = "select * from microsoftdns_" + recType + "Type where containername = '" + domain + "' and OwnerName = '" + cName + "." + domain + "'";
                ManagementObjectSearcher oS = new ManagementObjectSearcher(strQuery);
                oS.Scope = oMs;
                ManagementObjectCollection oRc = oS.Get();

        foreach (ManagementObject oR in oRc)
                {
                    returnServer = oR["RecordData"].ToString();
                }
        }
        catch (Exception e)
        {
            serviceLog.WriteEntry("Exception caught:\n\n" + e.ToString());
        }

    return returnServer;
}

它认为我在LineObjectCollection上收到错误oRc = oS.Get();

EDIT2:

客户端绑定:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IChangeDNS" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8216/ServiceChangeDNS/service"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IChangeDNS"
                contract="ServiceReference1.IChangeDNS" name="WSHttpBinding_IChangeDNS">
                <identity>
                    <servicePrincipalName value="host/MyComputerName.domain.local" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

服务绑定:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="ChangeDNSServiceBehavior" name="ChangeDNS.ChangeDNSService">
        <endpoint address="" binding="wsHttpBinding" contract="ChangeDNS.IChangeDNS" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8216/ServiceChangeDNS/service" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ChangeDNSServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

1 个答案:

答案 0 :(得分:0)

看起来你在客户端请求版画。那么当然,服务将在用户上下文中运行,而不是在自己的上下文中运行。您可以删除客户端上的模拟,如果您需要它,那么就可以执行该操作。