如何停止Windows.Web.Http.HttpClient上的凭证缓存?

13

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

  • 凭据(NTLM、Basic等)
  • OAuth(Bearer)

设置 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 Token

如果资源需要使用Bearer token,我会使用以下方法:

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

服务器凭据为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
       }
   }
}

问题

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

看起来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 是空的。

PasswordCredentialPropertyStore 有关的一些内容。

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

credentialPropertyStore是空的。

而且,PasswordCredentialPropertyStore 的方法 Clear 已被保留供内部使用,不应在你的代码中使用。

有什么想法吗?


我不知道具体情况,但是我猜测你可以在每个不同的请求中使用HttpClient并将其放在using块中进行关闭。当然,这只是一种解决方法。 - Vitor Canova
非常奇怪,即使离开了“using”块,它仍然保留凭据。看起来它在操作系统的用户级别被缓存了。 - Vitor Canova
如果这是针对Windows 8.1的,请求完成后您可以在控制面板的凭据管理器中找到密码吗?您可以尝试清除此请求的Uri的密码凭据, try { var credentials = _vault.FindAllByResource(PasswordVault); foreach(var passwordCredential in credentials) { _vault.Remove(passwordCredential); } } catch { // ignored } - Ahmed Rashad Mohamed
你尝试使用过 System.Net.Http 吗? - kiewic
如果您需要与WebView集成,那么这不是一个选项。 - kiewic
显示剩余2条评论
4个回答

3
感谢您报告此问题。这是操作系统中Windows.Web.Http.HttpClient API下层的低级WinINet HTTP堆栈已知的行为。一旦HTTP请求成功,凭据将缓存在该应用程序的进程内存中。因此,即使您创建新的HttpClient实例并将不同的凭据设置到HttpBaseProtocolFilter中,相同(原始)凭据仍然适用,并且只要它们在服务器端继续有效,就会被使用。(如果缓存的凭据在服务器端停止有效,则会用新提供的凭据覆盖它们。)
我们知道这个问题,并正在努力通过允许清除缓存的凭据来解决它。不幸的是,目前唯一的解决方法是让用户重启应用程序,这将清除应用程序的进程内存。这将允许首先使用不同的凭证。但是,只要它在服务器上有效,该凭据也将“粘着”于应用程序过程的其余部分。
谢谢,
Sidharth Nabar [Windows Networking团队]

Sidharth:感谢您的回答。这对我们来说是一个重大问题。在使用System.Web HttpClient时,Windows 8.1没有出现这种情况,但由于现在在UWP中使用WinInet,运行在UWP应用程序上下文中的现有代码(更重要的是SDK)可能存在重大安全问题,因为注销不再起作用。这应该是一个高优先级的问题。 - dotMorten
嗨@dotMorten,我们已经修复了这个问题,并且修复已包含在Insider Build 10586中(http://blogs.windows.com/windowsexperience/2015/11/05/announcing-windows-10-insider-preview-build-10586/)。请尝试在此版本上编译您的应用程序。另外,术语上稍作更正 - 我认为您指的是“System.Net.Http.HttpClient”,而不是“System.Web HttpClient”,对吗?谢谢 - Sidharth Nabar
谢谢@sidharth。不过我仍然可以重现这个问题。我会给你发一封带有复现步骤的邮件。 - dotMorten

1
只需添加 < /p >
uwp_bugs_never_got_fixed={something never repeat}

在您的请求URL查询参数中。

我已经将Nonce添加到URL查询参数中,但它并没有解决问题。 - Barnstokkr

1
这个问题现在已经解决,修复程序已包含在SDK的//build 2016版本中。此修复程序分为两部分:
  1. 从Windows build 10586开始,在同一应用程序中,新凭据可以覆盖旧的缓存值。因此,如果您使用了一个带有(userA,passwdA)的HttpClient c1实例,然后在同一应用程序中创建了一个新的客户端实例c2,其中包含了(userB,passwdB):这应该可以工作。新凭据将覆盖旧的缓存凭据(在早期版本中无法实现)。
  2. 然而,#1仍然不足以让您清除原始缓存凭据-您只能覆盖它们。为了支持清除缓存凭据,我们现在向HttpBaseProtocolFilter添加了一个方法-HttpBaseProtocolFilter.ClearAuthenticationCache(),它清除所有缓存的凭据信息。当您想要清除应用程序中过去的HttpClient实例中的凭据和/或客户端证书时,可以调用此方法。这种方法的文档很快就会在此处提供。
谢谢 Sidharth
[Windows Networking team]

谢谢Sidharth。我正在开发一个在10586上运行的UWP应用程序,但是我没有看到任何可用的HttpBaseProtocolFilter.ClearAuthenticationCache()?我正在使用已安装了“Tools(1.3.1)和Windows 10 SDK(10.0.10586)”的VS 2015更新2。我错过了什么吗? - 1iveowl
@JasperHedegaardBojsen - ClearAuthenticationCache API是最近才添加的(10586是2015年11月的版本)。 请通过Windows Insider计划使用Windows周年纪念版SDK预览版(版本14295)- http://insider.windows.com/ - Sidharth Nabar

0

对于遇到这个问题的人;

我在一个UWP电话应用程序中使用基本凭据也遇到了同样的问题;一旦用户成功验证了一次,它就会缓存这些凭据。即使关闭应用程序,甚至重新启动手机,它仍然存在。我当时真的怀疑是服务器端或其他方面的错误,但有一个类似的应用程序对同一服务器工作正常。

我发现添加以下代码可以解决问题:

filter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies

问题已解决。当输入正确的凭据时,一切正常,当尝试使用错误的凭据重试时,身份验证失败。这正是它应该做的!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接