摘要身份验证令牌在一段时间后无效

时间:2015-03-20 12:56:27

标签: c# iis windows-phone-8.1 servicestack digest-authentication

我正在开发我的第一个Windows Phone 8.1应用程序(如果这很重要,则通用,但目前仅实施Windows Phone)。起初所有工作都非常顺利,但只要我的应用程序运行大约25-30分钟,我就不能再使用我的HttpClient了。我使用Windows.Web.Http.HttpClient

在我的第一次尝试s I used a single HttpClient and reused it all the time. As I became aware that this is not working I started using a new HttpClient`中为每个请求。但仍然没有运气。

这是我获取新HttpClient的方法:

    private HttpClient GetClient()
    {
        var filter = new HttpBaseProtocolFilter
        {
            AllowUI = false,
            CacheControl = { WriteBehavior = HttpCacheWriteBehavior.NoCache },
            ServerCredential =
                new PasswordCredential(
                BaseApiUri.ToString(),
                credentials.UserName,
                credentials.Password),
        };

        var httpClient = new HttpClient(filter);
        var headers = httpClient.DefaultRequestHeaders;
        var httpConnectionOptionHeaderValueCollection = headers.Connection;
        httpConnectionOptionHeaderValueCollection.Clear();
        headers.Accept.TryParseAdd("application/json");
        headers.CacheControl.TryParseAdd("no-cache");
        headers.Add("Pragma", "no-cache");
        headers.Add("Keep-Alive", "false");
        headers.Cookie.Clear();

        return httpClient;
    }

设置标头和清除cookie的额外代码是我试图阻止可能发生的表面下某种连接的缓存。但仍然没有运气。

我的API请求方法如下:

    private async Task<bool> PostNoResponseRequestTo(string relativeUri, object requestContent, CancellationToken cancellationToken)
    {
        var targetUri = new Uri(BaseApiUri, relativeUri);
        var requestJson = JsonConvert.SerializeObject(requestContent);
        var content = new HttpStringContent(requestJson, UnicodeEncoding.Utf8, "application/json");
        try
        {
            using (var httpClient = this.GetClient())
            {
                var post =
                    await httpClient.PostAsync(targetUri, content).AsTask(cancellationToken).ContinueWith(
                        async request =>
                            {
                                using (var response = await request)
                                {
                                    return response.IsSuccessStatusCode;
                                }
                            },
                        cancellationToken);

                return await post;
            }
        }
        catch (Exception)
        {
            return false;
        }
    }

这适用于大约25-30分钟,之后对api的调用突然开始失败。我开始得到一个401,但你可以看到我已经指定了凭据,因为它们正在工作而且没有改变(硬编码它们来测试它)我开始相信问题出在API端。

这是我得到的回复:

StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 2, Content:      Windows.Web.Http.HttpStreamContent, Headers:
{
    Server: Microsoft-IIS/8.5
    Date: Fri, 20 Mar 2015 14:25:06 GMT
    WWW-Authenticate: Digest qop="auth",algorithm=MD5-sess,nonce="+Upgraded+NounceRemoved",charset=utf-8,realm="Digest", Negotiate, NTLM
    X-Powered-By: ASP.NET
}
{
    Content-Length: 1344
    Content-Type: text/html
}

我的API包含一个带有ServiceStack的Asp.Net项目,用于其API功能。 这是在具有激活的摘要式身份验证的IIS上运行的(所有其他都被禁用)。

通过检查日志,我意识到每次成功呼叫前面都有一个API调用失败。但如果我是对的,这是通过摘要身份验证的设计,因为我还没有找到告诉客户端对方正在使用摘要身份验证的方法。我能够在我的其他.Net项目中指定此类信息,但由于某种原因,Microsoft更改了HttpClient的代码(和命名空间)。我也知道你可以通过nuget获得原始命名空间中的HttpClient,但这对我不起作用,因为我在输出窗口中一旦出现任何调用就会出现错误。这会在没有任何信息的情况下关闭我的应用程序。

回到日志,我可以借助扩展日志记录和分析它们的工具获取一些信息。错误类似于(现在无法访问它将在以后编辑它):'传递给函数/方法的无效标记'。

我真的希望有人可以帮助我解决这个问题,因为它会使应用程序几乎无法使用。我的用户必须每隔15分钟重新启动应用程序才能进入保存站点。

感谢所有帮助我的建议。

1 个答案:

答案 0 :(得分:3)

尝试在IIS中检查计算机密钥设置。如果tick在每次重新启动应用程序池时都会生成新密钥,则在运行时自动生成。这可能会导致您的问题。可以在服务器,网站或应用程序级别设置机器密钥。由于激活的摘要式身份验证已加密,因此可能存在问题。

Managing Websites with IIS Manager (part 6) - The Machine Key and Windows Authentication