HttpClient和Windows Auth:将用户的消费者登录到服务

我正在努力理解并建立一个服务和消费者,服务将在用户登录消费者时运行。

我的消费者是一个MVC应用程序。 我的服务是一个Web Api应用程序。 两者都在同一域内的不同服务器上运行。 两者都设置为使用Windows身份validation。

我的消费者代码是:

private T GenericGet(string p) { T result = default(T); HttpClientHandler handler = new HttpClientHandler() { PreAuthenticate = true, UseDefaultCredentials = true }; using (HttpClient client = new HttpClient(handler)) { client.BaseAddress = new Uri(serviceEndPoint); HttpResponseMessage response = client.GetAsync(p).Result; if (response.IsSuccessStatusCode) result = response.Content.ReadAsAsync().Result; } return result; } 

在我的服务中,我调用User.Identity.Name来获取调用者ID,但这总是作为消费者应用程序池ID返回,而不是登录用户。 消费者应用程序池作为网络服务运行,服务器本身受信任以进行委派。 那么我如何获得登录用户? 服务代码:

  // GET: /Modules/5/Permissions/ [Authorize] public ModulePermissionsDTO Get(int ModuleID) { Module module= moduleRepository.Find(ModuleID); if (module== null) throw new HttpResponseException(HttpStatusCode.NotFound); // This just shows as the App Pool the MVC consumer is running as (Network Service). IPrincipal loggedInUser = User; // Do I need to do something with this instead? string authHeader = HttpContext.Current.Request.Headers["Authorization"]; ModulePermissionsDTO dto = new ModulePermissionsDTO(); // Construct object here based on User... return dto; } 

根据这个问题 ,Kerberos需要使这个设置工作,因为HttpClient在一个单独的线程中运行。 然而,这让我感到困惑,因为我认为请求发送了Authorization标头,因此服务应该能够使用它并检索用户令牌。 无论如何,我已经使用Kerberos进行了一些测试,使用“情境5”中的演示检查这是否正确地在我的域上工作,这可行,但我的两个应用程序仍然无法正确传递登录用户。

那么我需要做些什么来使这项工作? 是否需要Kerberos或者我是否需要在我的服务中执行某些操作来解压缩Authorization标头并从令牌创建主体对象? 所有建议表示赞赏

关键是让你的MVC应用程序(消费者)模拟调用用户,然后同步发出HTTP请求(即不产生新线程)。 您不必关心低级实现细节,例如NTLM vs Kerberos。

消费者

像这样配置你的MVC应用程序:

  1. 启动IIS管理器
  2. 选择您的MVC Web应用程序
  3. 双击“身份validation”
  4. 启用 “ASP.NET模拟”
  5. 启用 “Windows身份validation”
  6. 禁用其他forms的身份validation(除非您需要,否则可能是Digest)
  7. 打开MVC应用程序根目录中的Web.config文件,并确保

要发出HTTP请求,我建议您使用优秀的RestSharp库。 例:

 var client = new RestClient(""); client.Authenticator = new NtlmAuthenticator(); var request = new RestRequest("Modules/5/Permissions", Method.GET); var response = client.Execute(request); 

服务

像这样配置Web API服务:

  1. 启动IIS管理器
  2. 选择您的Web API服务
  3. 双击“身份validation”
  4. 禁用 “ASP.NET模拟”。
  5. 启用 “Windows身份validation”
  6. 如果只有一部分Web API方法要求对用户进行身份validation,请启用“匿名身份validation”。
  7. 打开Web API服务根目录中的Web.config文件,并确保

我可以看到你已经使用[Authorize]属性修饰了你的方法,该属性在访问方法时应该触发认证质询(HTTP 401)。 现在,您应该能够通过ApiController类的User.Identity属性访问最终用户的身份。

双跃点的关键问题是将用户凭证委托给第二次呼叫。 我想详细说明一下。 C1 =客户端浏览器,S1 =第一服务器,S2 =第二服务器。

假设我们的完整系统支持窗口validation。 当用户从浏览器访问S1时,其默认窗口凭据传递给服务器S1,但是当S1调用S2时,默认情况下它不会将凭证传递给S2。

解析度 :

  1. 我们必须在两台机器上启用窗口身份validation/模拟。
  2. 我们需要在服务器之间启用委派,以便S1可以信任S2并将凭证传递给S2。

您可以在以下链接中找到一些有用的详细信息:http://blogs.msdn.com/b/farukcelik/archive/2008/01/02/how-to-set-up-a-kerberos-authentication-scenario-with- SQL服务器连接 – servers.aspx

https://sqlbadboy.wordpress.com/2013/10/11/the-kerberos-double-hop-problem/

如果您尝试访问托管在Windows身份validation上的服务,请执行以下操作。

 var request = new RestRequest(Method.POST); 

如果要使用必须在托管服务服务器上具有访问权限的应用程序默认凭据

 request.UseDefaultCredentials = true; 

以下用户手动传递凭据

 request.Credentials = new NetworkCredential("Username", "Password", "Domain");