如何通过 Windows 身份验证在来自控制台应用程序的 Web API 调用中传递模拟用户?

How to pass impersonated user in Web API call from Console App with Windows Authentication?

我有一个控制台应用程序和一个 Web API 2 项目,两者都 运行 在同一台服务器上。我已将控制台应用程序设置为在模拟域帐户时使用 HttpClient 在我的 Web API 中调用 RESTful 端点。

            Console.WriteLine("Setting up impersonator.");
            using (new Impersonator(accountUsername, accountDomain, accountPwd))
            {
                Console.WriteLine("Impersonator set up.");

                HttpClientHandler handler = new HttpClientHandler();
                handler.UseDefaultCredentials = true;

                Console.WriteLine("Executing as: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);

                using (var client = new HttpClient(handler))
                {
                    client.BaseAddress = new Uri(serviceBaseUrl);
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    HttpResponseMessage response = await client.GetAsync("api/resource/3/");
                    Console.WriteLine(response.ToString());
                    if (response.IsSuccessStatusCode)
                    {
                        result = await response.Content.ReadAsAsync<ResourceType>();
                    }
                }

                if (result != null)
                {
                    // Do something...
                }
            }

我认为实际端点与这个问题无关,因为 Http 请求从未达到这一点(即使没有任何授权属性)。当我在本地运行这两个项目时,Console App在调用时是成功的。但是,当我 运行 它在服务器上时,控制台应用程序收到 401 未经授权。我在 Web API 管道中添加了一些日志记录以记录 HttpContext.Current.User 信息。

    protected void Application_BeginRequest()
    {
        var currentContext = HttpContext.Current;
        ILogHelper _logger = new LogHelper("System");

        _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "BeginRequest System Principal Name: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
        _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "BeginRequest Is User Null? " + (currentContext.User == null? "YES":"NO"));

        if (currentContext.User != null)
        {
            _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "BeginRequest User: " + currentContext.User.Identity.Name);
            _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "BeginRequest User Authenticated: " + currentContext.User.Identity.IsAuthenticated.ToString());
        }
    }

    protected void Application_AuthenticateRequest()
    {
        var currentContext = HttpContext.Current;
        ILogHelper _logger = new LogHelper("System");

        _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthenticateRequest System Principal Name: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
        _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthenticateRequest Is User Null? " + (currentContext.User == null ? "YES" : "NO"));

        if (currentContext.User != null)
        {
            _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthenticateRequest User: " + currentContext.User.Identity.Name);
            _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthenticateRequest User Authenticated: " + currentContext.User.Identity.IsAuthenticated.ToString());
        }
    }

    protected void Application_AuthorizeRequest()
    {
        var currentContext = HttpContext.Current;
        ILogHelper _logger = new LogHelper("System");

        _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthorizeRequest System Principal Name: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
        _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthorizeRequest Is User Null? " + (currentContext.User == null ? "YES" : "NO"));

        if (currentContext.User != null)
        {
            _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthorizeRequest User: " + currentContext.User.Identity.Name);
            _logger.LogLine(NLog.LogLevel.Info, LogHelper.Tier.Business, "AuthorizeRequest User Authenticated: " + currentContext.User.Identity.IsAuthenticated.ToString());
        }
    }

当 运行 在本地时,模拟用户登录 'AuthenticateRequest' 和 'AuthorizeRequest'。但是,当服务器上 运行 时,用户在整个管道中都是空的。

我在 IIS 中启用了 Windows 身份验证和模拟(禁用所有其他功能)。我已经为此工作了 40 多个小时,但感觉自己没有取得任何进展。对这个问题的任何帮助都是巨大的!

从这个 , I determined that it is, in fact, a FQDN problem. To "fix", I just had to change out the "servername.com/service/" base URL in my Web.config with "localhost/service/". Once I did this, it ran flawlessly. I don't like the thought of using localhost as the URL, but I am unable to edit the server Registry values, so the fix provided by Microsoft 对我不起作用。

此外,事实证明我不需要在 IIS 的 Web API 站点上启用模拟。现在,我只启用了 Windows 身份验证。