如何停止 Windows.Web.Http.HttpClient 上的凭据缓存?
How to stop credential caching on Windows.Web.Http.HttpClient?
我遇到一个问题,应用程序尝试使用不同的身份验证方法从同一服务器访问资源,这两种方法是:
- 凭据(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 令牌
如果资源需要我使用的 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
请求 returns 200(OK),那么每个后续 Bearer
请求也 returns 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
为空。
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.
有什么想法吗?
感谢您报告此问题。这是位于操作系统 Windows.Web.Http.HttpClient API 下方的低级 WinINet HTTP 堆栈中的已知行为。一旦 HTTP 请求成功,凭据就会缓存在该应用程序的进程内存中。因此,即使您创建一个新的 HttpClient 实例并在 HttpBaseProtocolFilter 中设置不同的凭据,只要它们在服务器端继续有效,相同的(原始)凭据就会应用并被使用。 (如果缓存的凭证在服务器端不再有效,它们将被新提供的凭证覆盖。)
我们已注意到此问题,并正在努力通过允许清除缓存的凭据来解决此问题。不幸的是,目前唯一的解决方法是让用户重新启动应用程序,这将清除应用程序的进程内存。这将允许首先使用不同的凭证。但是,只要该凭据在服务器上有效,该凭据也将 'stick' 用于申请流程的其余部分。
谢谢,
西达尔斯·纳巴尔
[Windows 网络团队]
对于遇到这个问题的人;
我在 UWP Phone 应用程序上遇到了与基本凭据相同的问题;一旦用户成功通过身份验证,它就会缓存这些凭据。即使关闭应用程序,即使重新启动 phone。老实说,我怀疑服务器端存在错误,但有一个类似的应用程序在同一台服务器上按预期工作。
我发现添加:
filter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies
解决了我的问题。输入正确的凭据时一切正常,当使用错误的凭据重试时身份验证失败。正如它应该做的那样!
只需追加
uwp_bugs_never_got_fixed={something never repeat}
在你的请求中URL查询参数。
此问题现已解决,修复程序包含在 //build 2016 版本的 SDK 中。此修复分为两个部分:
在 Windows build 10586 之后,新凭据可以覆盖同一应用中的旧缓存值。因此,如果您使用带有 (userA, passwordA) 的 HttpClient c1 实例,然后在同一个应用程序中使用 (userB, passwordA) 创建了一个新的客户端实例 c2:这应该可以工作。新凭据会覆盖旧的缓存凭据(这在早期版本中不起作用)。
但是,#1 仍然不足以让您清除原始缓存的凭据 - 您只能覆盖它们。为了支持清除缓存的凭据,我们现在向 HttpBaseProtocolFilter 添加了一个方法 - HttpBaseProtocolFilter.ClearAuthenticationCache() 以清除所有缓存的凭据信息。当您想要从您的应用程序中过去的 HttpClient 实例中清除凭据 and/or 客户端证书时,您可以调用此方法。此方法的文档将很快可用 here
谢谢
西达尔斯
[Windows 网络团队]
我遇到一个问题,应用程序尝试使用不同的身份验证方法从同一服务器访问资源,这两种方法是:
- 凭据(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 令牌
如果资源需要我使用的 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
请求 returns 200(OK),那么每个后续 Bearer
请求也 returns 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
为空。
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.
有什么想法吗?
感谢您报告此问题。这是位于操作系统 Windows.Web.Http.HttpClient API 下方的低级 WinINet HTTP 堆栈中的已知行为。一旦 HTTP 请求成功,凭据就会缓存在该应用程序的进程内存中。因此,即使您创建一个新的 HttpClient 实例并在 HttpBaseProtocolFilter 中设置不同的凭据,只要它们在服务器端继续有效,相同的(原始)凭据就会应用并被使用。 (如果缓存的凭证在服务器端不再有效,它们将被新提供的凭证覆盖。)
我们已注意到此问题,并正在努力通过允许清除缓存的凭据来解决此问题。不幸的是,目前唯一的解决方法是让用户重新启动应用程序,这将清除应用程序的进程内存。这将允许首先使用不同的凭证。但是,只要该凭据在服务器上有效,该凭据也将 'stick' 用于申请流程的其余部分。
谢谢,
西达尔斯·纳巴尔 [Windows 网络团队]
对于遇到这个问题的人;
我在 UWP Phone 应用程序上遇到了与基本凭据相同的问题;一旦用户成功通过身份验证,它就会缓存这些凭据。即使关闭应用程序,即使重新启动 phone。老实说,我怀疑服务器端存在错误,但有一个类似的应用程序在同一台服务器上按预期工作。
我发现添加:
filter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies
解决了我的问题。输入正确的凭据时一切正常,当使用错误的凭据重试时身份验证失败。正如它应该做的那样!
只需追加
uwp_bugs_never_got_fixed={something never repeat}
在你的请求中URL查询参数。
此问题现已解决,修复程序包含在 //build 2016 版本的 SDK 中。此修复分为两个部分:
在 Windows build 10586 之后,新凭据可以覆盖同一应用中的旧缓存值。因此,如果您使用带有 (userA, passwordA) 的 HttpClient c1 实例,然后在同一个应用程序中使用 (userB, passwordA) 创建了一个新的客户端实例 c2:这应该可以工作。新凭据会覆盖旧的缓存凭据(这在早期版本中不起作用)。
但是,#1 仍然不足以让您清除原始缓存的凭据 - 您只能覆盖它们。为了支持清除缓存的凭据,我们现在向 HttpBaseProtocolFilter 添加了一个方法 - HttpBaseProtocolFilter.ClearAuthenticationCache() 以清除所有缓存的凭据信息。当您想要从您的应用程序中过去的 HttpClient 实例中清除凭据 and/or 客户端证书时,您可以调用此方法。此方法的文档将很快可用 here
谢谢 西达尔斯
[Windows 网络团队]