Marked CookieTempDataProvider's cookie as non-essential
[Fixes #7160] Determine if the temp data cookie is considered essential
This commit is contained in:
parent
1fa1d7df3e
commit
9fd60ff864
|
|
@ -12,6 +12,7 @@
|
|||
<MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>2.1.0-preview1-27965</MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.0-preview1-27965</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion>2.1.0-preview1-27965</MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreCookiePolicyPackageVersion>2.1.0-preview1-27965</MicrosoftAspNetCoreCookiePolicyPackageVersion>
|
||||
<MicrosoftAspNetCoreCorsPackageVersion>2.1.0-preview1-27965</MicrosoftAspNetCoreCorsPackageVersion>
|
||||
<MicrosoftAspNetCoreDiagnosticsAbstractionsPackageVersion>2.1.0-preview1-27965</MicrosoftAspNetCoreDiagnosticsAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.1.0-preview1-27965</MicrosoftAspNetCoreDiagnosticsPackageVersion>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
HttpOnly = true,
|
||||
SameSite = SameSiteMode.Strict,
|
||||
|
||||
// This cookie has been marked as non-essential because a user could use the SessionStateTempDataProvider,
|
||||
// which is more common in production scenarios. Check the comment on CookieBuilder below
|
||||
// for more information.
|
||||
IsEssential = false,
|
||||
|
||||
// Some browsers do not allow non-secure endpoints to set cookies with a 'secure' flag or overwrite cookies
|
||||
// whose 'secure' flag is set (http://httpwg.org/http-extensions/draft-ietf-httpbis-cookie-alone.html).
|
||||
// Since mixing secure and non-secure endpoints is a common scenario in applications, we are relaxing the
|
||||
|
|
@ -33,7 +38,11 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// <para>
|
||||
/// <see cref="CookieBuilder.SameSite"/> defaults to <see cref="SameSiteMode.Strict"/>.
|
||||
/// <see cref="CookieBuilder.SecurePolicy"/> defaults to <see cref="CookieSecurePolicy.SameAsRequest" />.
|
||||
/// <see cref="CookieBuilder.HttpOnly"/> defaults to <c>true</c>
|
||||
/// <see cref="CookieBuilder.HttpOnly"/> defaults to <c>true</c>.
|
||||
/// <see cref="CookieBuilder.IsEssential"/> defaults to <c>false</c>, This property is only considered when a
|
||||
/// user opts into the CookiePolicyMiddleware. If you are using this middleware and want to use
|
||||
/// <see cref="CookieTempDataProvider"/>, then either set this property to <c>true</c> or
|
||||
/// request user consent for non-essential cookies.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public CookieBuilder Cookie
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class TempDataInCookiesUsingCookieConsentTest
|
||||
: IClassFixture<MvcTestFixture<BasicWebSite.StartupWithCookieTempDataProviderAndCookieConsent>>
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
|
||||
public TempDataInCookiesUsingCookieConsentTest(
|
||||
MvcTestFixture<BasicWebSite.StartupWithCookieTempDataProviderAndCookieConsent> fixture)
|
||||
{
|
||||
_client = fixture.Client;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CookieTempDataProviderCookie_SetInResponse_OnGrantingConsent()
|
||||
{
|
||||
// Arrange
|
||||
var nameValueCollection = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("value", "Foo"),
|
||||
};
|
||||
var content = new FormUrlEncodedContent(nameValueCollection);
|
||||
// This response would have the consent cookie which would be sent on rest of the requests here
|
||||
var response = await _client.GetAsync("/TempData/GrantConsent");
|
||||
|
||||
// Act 1
|
||||
response = await _client.SendAsync(GetPostRequest("/TempData/SetTempData", content, response));
|
||||
|
||||
// Assert 1
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
// Act 2
|
||||
response = await _client.SendAsync(GetRequest("/TempData/GetTempData", response));
|
||||
|
||||
// Assert 2
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("Foo", body);
|
||||
|
||||
// Act 3
|
||||
response = await _client.SendAsync(GetRequest("/TempData/GetTempData", response));
|
||||
|
||||
// Assert 3
|
||||
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CookieTempDataProviderCookie_NotSetInResponse_OnNoConsent()
|
||||
{
|
||||
// Arrange
|
||||
var nameValueCollection = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("value", "Foo"),
|
||||
};
|
||||
var content = new FormUrlEncodedContent(nameValueCollection);
|
||||
|
||||
// Act 1
|
||||
var response = await _client.PostAsync("/TempData/SetTempData", content);
|
||||
|
||||
// Assert 1
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
// Act 2
|
||||
response = await _client.SendAsync(GetRequest("/TempData/GetTempData", response));
|
||||
|
||||
// Assert 2
|
||||
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
|
||||
}
|
||||
|
||||
private HttpRequestMessage GetRequest(string path, HttpResponseMessage response)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, path);
|
||||
SetCookieHeaders(request, response);
|
||||
return request;
|
||||
}
|
||||
|
||||
private HttpRequestMessage GetPostRequest(string path, HttpContent content, HttpResponseMessage response)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, path);
|
||||
request.Content = content;
|
||||
SetCookieHeaders(request, response);
|
||||
return request;
|
||||
}
|
||||
|
||||
private void SetCookieHeaders(HttpRequestMessage request, HttpResponseMessage response)
|
||||
{
|
||||
IEnumerable<string> values;
|
||||
if (response.Headers.TryGetValues("Set-Cookie", out values))
|
||||
{
|
||||
foreach (var cookie in SetCookieHeaderValue.ParseList(values.ToList()))
|
||||
{
|
||||
if (cookie.Expires == null || cookie.Expires >= DateTimeOffset.UtcNow)
|
||||
{
|
||||
request.Headers.Add("Cookie", new CookieHeaderValue(cookie.Name, cookie.Value).ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,5 +13,6 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Session" Version="$(MicrosoftAspNetCoreSessionPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(MicrosoftAspNetCoreDiagnosticsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="$(MicrosoftAspNetCoreCookiePolicyPackageVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Threading.Tasks;
|
||||
using BasicWebSite.Filters;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BasicWebSite.Controllers
|
||||
|
|
@ -117,5 +118,11 @@ namespace BasicWebSite.Controllers
|
|||
{
|
||||
return TempData[nameof(UnhandledExceptionAndSettingTempData)]?.ToString();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void GrantConsent()
|
||||
{
|
||||
HttpContext.Features.Get<ITrackingConsentFeature>().GrantConsent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BasicWebSite
|
||||
{
|
||||
public class StartupWithCookieTempDataProviderAndCookieConsent
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc();
|
||||
|
||||
services.Configure<CookiePolicyOptions>(o =>
|
||||
{
|
||||
o.CheckConsentNeeded = httpContext => true;
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
||||
app.UseCookiePolicy();
|
||||
|
||||
app.UseMvcWithDefaultRoute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue