17

我正在努力理解和设置一个服务和消费者,当用户登录到消费者时,服务将在其中运行。

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

我的消费者代码是:

private T GenericGet<T>(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<T>().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 标头并从令牌创建一个主体对象?所有建议表示赞赏。

4

3 回答 3

16

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

消费者

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

  1. 启动 IIS 管理器
  2. 选择您的 MVC Web 应用程序
  3. 双击“身份验证”
  4. 启用“ASP.NET 模拟”
  5. 启用“Windows 身份验证”
  6. 禁用其他形式的身份验证(除非您需要 Digest)
  7. 打开 MVC 应用程序根目录中的 Web.config 文件并确保<authentication mode="Windows" />

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

var client = new RestClient("<your base url here>");
client.Authenticator = new NtlmAuthenticator();
var request = new RestRequest("Modules/5/Permissions", Method.GET);
var response = client.Execute<ModulePermissionsDTO>(request);

服务

像这样配置您的 Web API 服务:

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

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

于 2013-10-14T11:36:40.810 回答
0

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

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

解析度 :

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

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

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

于 2015-07-14T10:41:48.247 回答
0

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

var request = new RestRequest(Method.POST);

如果您想使用必须有权访问托管服务服务器的应用程序默认凭据

request.UseDefaultCredentials = true;

下面的用户手动传递凭据

request.Credentials = new NetworkCredential("Username", "Password", "Domain");
于 2017-12-06T14:46:52.307 回答