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

时间:2015-06-09 11:59:46

标签: c# windows-phone-8.1 windows-8.1 httpclient win-universal-app

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

  • 凭证(NTLM,基本等)
  • 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令牌

如果资源需要Bearer令牌,我使用:

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

ServerCredential为空

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令牌无效,每个后续Bearer请求也会返回200(OK)并且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为空。

PasswordCredentialPropertyStore

的东西
Windows.Security.Credentials.PasswordCredentialPropertyStore credentialPropertyStore = new Windows.Security.Credentials.PasswordCredentialPropertyStore();

credentialPropertyStore为空。

PasswordCredentialPropertyStore的方法清除is reserved for internal use and is not intended to be used in your code.

有什么想法吗?

4 个答案:

答案 0 :(得分:3)

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

我们知道这个问题,并正在努力通过允许清除缓存凭据来纠正它。不幸的是,目前唯一的解决方法是让用户重启应用程序,这将清除应用程序的进程内存。这将允许首先使用不同的凭证。但是,该凭证也将“坚持”。对于应用程序进程的其余部分,只要它在服务器上有效。

谢谢,

Sidharth Nabar [Windows网络团队]

答案 1 :(得分:1)

只需附加

uwp_bugs_never_got_fixed={something never repeat}

在您的请求网址查询参数中。

答案 2 :(得分:1)

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

  1. 在Windows版本10586之后,新凭据可以覆盖同一应用程序中较旧的缓存值。因此,如果您使用HttpClient c1的实例(userA,paswordA),然后在同一个应用程序中创建一个新的客户端实例c2(userB,passwdB):这应该可行。新凭据会覆盖旧的缓存(这在早期版本中不起作用)。

  2. 但是,#1仍然不足以让您清除原始缓存凭据 - 您只能覆盖它们。为了支持清除缓存凭据,我们现在为HttpBaseProtocolFilter添加了一个方法 - HttpBaseProtocolFilter.ClearAuthenticationCache() ,它清除所有缓存的凭据信息。如果要从应用程序中的过去HttpClient实例中清除凭据和/或客户端证书,可以调用此方法。该方法的文档很快就会出现here

  3. 由于 Sidharth

    [Windows网络团队]

答案 3 :(得分:0)

对于任何面临此问题的人;

我在UWP手机应用上遇到了与基本凭证相同的问题;一旦用户成功进行一次身份验证,就会缓存这些凭据。即使在关闭应用程序时,即使重新启动手机也是如此。老实说,我怀疑服务器端有一个错误,但是有一个类似的应用程序可以按照预期在同一服务器上运行。

我发现添加:

filter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies

解决了我的问题。输入正确的凭据时,一切都很好,当使用虚假凭据进行重试时,身份验证失败。正如它本应该做的那样!