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

Jam*_*mes 14 c# authentication asp.net-mvc web-services asp.net-web-api

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

我的消费者是一个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;
    }
Run Code Online (Sandbox Code Playgroud)

在我的服务中,我打电话User.Identity.Name来获取来电显示,但这总是作为消费者应用程序池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;
    }
Run Code Online (Sandbox Code Playgroud)

根据这个问题,Kerberos需要使这个设置工作,因为HttpClient在一个单独的线程中运行.然而,这让我感到困惑,因为我认为请求发送了Authorization标头,因此服务应该能够使用它并检索用户令牌.无论如何,我已经做了一些测试使用Kerberos,以检查该正确适用于我的域名使用演示在"境遇5" 在这里,这工作,但我的两个应用程序仍然不会正确地传递跨越登录的用户.

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

Eir*_*son 14

关键是让你的MVC应用程序(消费者)模拟调用用户,然后同步发出HTTP请求(即不产生新线程).您不必关心低级实现细节,例如NTLM vs 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);
Run Code Online (Sandbox Code Playgroud)

服务

像这样配置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类的属性访问最终用户的身份.