Merge pull request #179 from aspnet/artakm/ReadonlyHeadersResetFix

Updated the DefaultAntiforgery to set the the cache headers only if the Response hasn't started yet
This commit is contained in:
Artak Mkrtchyan 2018-01-22 22:19:23 -08:00 коммит произвёл GitHub
Родитель e5de4e672c 18bd033d8e
Коммит 4c84463ad4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 68 добавлений и 4 удалений

Просмотреть файл

@ -67,9 +67,12 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
}
}
// Explicitly set the cache headers to 'no-cache'. This could override any user set value but this is fine
// as a response with antiforgery token must never be cached.
SetDoNotCacheHeaders(httpContext);
if (!httpContext.Response.HasStarted)
{
// Explicitly set the cache headers to 'no-cache'. This could override any user set value but this is fine
// as a response with antiforgery token must never be cached.
SetDoNotCacheHeaders(httpContext);
}
return tokenSet;
}
@ -247,7 +250,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
_logger.ReusedCookieToken();
}
SetDoNotCacheHeaders(httpContext);
if (!httpContext.Response.HasStarted)
{
SetDoNotCacheHeaders(httpContext);
}
}
private void SaveCookieTokenAndHeader(HttpContext httpContext, string cookieToken)

Просмотреть файл

@ -6,6 +6,7 @@ using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
@ -1137,6 +1138,47 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
context.TokenSerializer.Verify(s => s.Deserialize(null), Times.Never);
}
[Fact]
public void SetCookieTokenAndHeader_DoesNotModifyHeadersAfterResponseHasStarted()
{
// Arrange
var antiforgeryFeature = new AntiforgeryFeature
{
HaveDeserializedCookieToken = false,
HaveGeneratedNewCookieToken = false,
HaveStoredNewCookieToken = true,
NewCookieToken = new AntiforgeryToken(),
NewCookieTokenString = "serialized-cookie-token-from-context",
NewRequestToken = new AntiforgeryToken(),
NewRequestTokenString = "serialized-form-token-from-context",
};
var context = CreateMockContext(
new AntiforgeryOptions(),
useOldCookie: false,
isOldCookieValid: false,
antiforgeryFeature: antiforgeryFeature);
var testTokenSet = new TestTokenSet
{
OldCookieTokenString = null
};
var nullTokenStore = GetTokenStore(context.HttpContext, testTokenSet, false);
var antiforgery = GetAntiforgery(
context.HttpContext,
tokenGenerator: context.TokenGenerator.Object,
tokenStore: nullTokenStore.Object);
TestResponseFeature testResponse = new TestResponseFeature();
context.HttpContext.Features.Set<IHttpResponseFeature>(testResponse);
context.HttpContext.Response.Headers["Cache-Control"] = "public";
testResponse.StartResponse();
// Act
antiforgery.SetCookieTokenAndHeader(context.HttpContext);
Assert.Equal("public", context.HttpContext.Response.Headers["Cache-Control"]);
}
[Fact]
public void GetAndStoreTokens_DoesNotLogWarning_IfNoExistingCacheHeadersPresent()
{
@ -1435,5 +1477,21 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
{
public AntiforgeryOptions Value { get; set; } = new AntiforgeryOptions();
}
private class TestResponseFeature : HttpResponseFeature
{
private bool _hasStarted = false;
public override bool HasStarted { get => _hasStarted; }
public TestResponseFeature()
{
}
public void StartResponse()
{
_hasStarted = true;
}
}
}
}