如何在Windows.Web.Http.HttpClient上停止凭据缓存

本文关键字:缓存 HttpClient Windows Web Http | 更新日期: 2023-09-27 17:54:44

我遇到了一个问题,一个应用程序试图使用不同的身份验证方法从同一服务器访问资源,这两种方法是:

  • 凭据(NTLM、Basic等)
  • OAuth(持票人)

设置HttpBaseProtocolFilter

HttpBaseProtocolFilter设置为:

  • 禁用缓存
  • 禁用自动UI凭据请求弹出

HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;
filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.MostRecent;
filter.AllowUI = false;

添加服务器凭据

如果资源需要凭据,那么我使用:

filter.ServerCredential = new PasswordCredential(
                RequestUri.ToString(),
                UserName,
                Password);
HttpClient httpClient = new HttpClient(filter);

添加OAuth令牌

如果资源需要一个承载令牌,我使用:

HttpClient httpClient = new HttpClient(filter);
httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("Bearer", token);

ServerCredential为null

filter.ServerCredential = null

从服务器获取响应

using(httpClient)
{
   using(HttpRequestMessage requestMessage = new HttpRequestMessage(new HttpMethod(method), RequestUri))
   {
       using(HttpResponseMessage response = await httpClient.SendRequestAsync(requestMessage))
       {
           // Do something with response
       }
   }
}

如果HttpClient请求使用ServerCredential返回200 (OK),那么每个Bearer请求也返回200 (OK),即使Bearer令牌无效且filter.ServerCredential为空。

看起来好像filter.ServerCredential被缓存了,所有后续调用都使用缓存的凭据进行身份验证。

我必须重新启动应用程序,如果我想做一个Bearer认证。

如何删除、禁用或清除Windows.Web.Http.HttpClient的ServerCredential ?


我尝试过的事情:

删除所有cookie

var cookieManager = filter.CookieManager;
HttpCookieCollection myCookieJar = cookieManager.GetCookies(RequestUri);
foreach (HttpCookie cookie in myCookieJar)
{
    cookieManager.DeleteCookie(cookie);
}

myCookieJar为空

Something with PasswordCredentialPropertyStore

Windows.Security.Credentials.PasswordCredentialPropertyStore credentialPropertyStore = new Windows.Security.Credentials.PasswordCredentialPropertyStore();

credentialPropertyStore为空

PasswordCredentialPropertyStore的Clear方法保留给内部使用,不打算在您的代码中使用。

任何想法?

如何在Windows.Web.Http.HttpClient上停止凭据缓存

感谢您报告此问题。这是操作系统中位于Windows.Web.Http.HttpClient API下面的底层WinINet HTTP栈中的一种已知行为。一旦HTTP请求成功,凭据就会缓存到该应用程序的进程内存中。因此,即使你创建了一个新的HttpClient实例,并在HttpBaseProtocolFilter中设置了不同的凭据,只要相同的(原始)凭据在服务器端继续有效,就会应用并使用。(如果缓存的凭证在服务器端不再有效,它们将被新提供的凭证覆盖。)

我们已经意识到这个问题,并正在通过允许清除缓存凭据来纠正它。不幸的是,目前唯一的解决方案是让用户重新启动应用程序,这将清除应用程序的进程内存。这将允许首先使用不同的凭据。但是,只要该凭据在服务器上有效,该凭据也将在其余的应用程序过程中"保留"。

谢谢,

Sidharth Nabar[Windows网络团队]

此问题现已解决,修复包含在//build 2016版本的SDK中。这个修复有两个部分:

  1. 在Windows构建10586起,新的凭证可以覆盖旧的缓存值在同一个应用程序。所以,如果你使用的是一个实例的HttpClient c1与(userA, passwda),然后创建一个新的客户端实例c2与(userB, passwdB)在同一个应用程序:这应该工作。新凭据覆盖旧的缓存凭据(这在早期版本中不起作用)。

  2. 但是,#1仍然不足以让您清除原始缓存的凭据—您只能覆盖它们。为了支持清除缓存的凭据,我们现在在HttpBaseProtocolFilter - HttpBaseProtocolFilter. clearauthenticationcache ()中添加了一个方法来清除所有缓存的凭据信息。当你想从你的应用中过去的HttpClient实例中清除凭据和/或客户端证书时,你可以调用这个方法。关于这个方法的文档将很快在这里提供

谢谢Sidharth

[Windows Networking team]

添加

uwp_bugs_never_got_fixed={something never repeat}

对于任何面临这个问题的人;

我在UWP手机应用程序上的基本凭据也有同样的问题;一旦用户成功通过身份验证,它就会缓存这些凭据。即使在关闭应用程序时,即使在重新启动手机时。我真的怀疑服务器端有bug,但是有一个类似的应用程序在相同的服务器上工作。

我发现添加:

filter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies

解决了我的问题。当输入正确的凭据时一切正常,当使用错误的凭据重试时身份验证失败。就像它应该做的那样!