From 32710bbfbea53349ba187610588bbbc96ad51cb4 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Fri, 28 Oct 2016 14:08:34 -0700 Subject: [PATCH] [#5430] CookieTempDataProvider chunking broken --- .../ViewFeatures/CookieTempDataProvider.cs | 11 +++++---- .../TempDataInCookiesTest.cs | 23 ++++++++++++++----- .../project.json | 4 ++++ .../CookieTempDataProviderTest.cs | 19 +++++++-------- 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/CookieTempDataProvider.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/CookieTempDataProvider.cs index f232175d2d..81b012cb32 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/CookieTempDataProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/CookieTempDataProvider.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.WebUtilities; using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; using Microsoft.Extensions.Options; @@ -41,10 +42,10 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures if (context.Request.Cookies.ContainsKey(CookieName)) { - var base64EncodedValue = _chunkingCookieManager.GetRequestCookie(context, CookieName); - if (!string.IsNullOrEmpty(base64EncodedValue)) + var encodedValue = _chunkingCookieManager.GetRequestCookie(context, CookieName); + if (!string.IsNullOrEmpty(encodedValue)) { - var protectedData = Convert.FromBase64String(base64EncodedValue); + var protectedData = Base64UrlTextEncoder.Decode(encodedValue); var unprotectedData = _dataProtector.Unprotect(protectedData); return _tempDataSerializer.Deserialize(unprotectedData); } @@ -73,8 +74,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures { var bytes = _tempDataSerializer.Serialize(values); bytes = _dataProtector.Protect(bytes); - var base64EncodedValue = Convert.ToBase64String(bytes); - _chunkingCookieManager.AppendResponseCookie(context, CookieName, base64EncodedValue, cookieOptions); + var encodedValue = Base64UrlTextEncoder.Encode(bytes); + _chunkingCookieManager.AppendResponseCookie(context, CookieName, encodedValue, cookieOptions); } else { diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TempDataInCookiesTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TempDataInCookiesTest.cs index ed60b12c0d..5df7dcfa2c 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TempDataInCookiesTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TempDataInCookiesTest.cs @@ -1,17 +1,19 @@ // 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.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; +using Microsoft.AspNetCore.Internal; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Net.Http.Headers; using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests { public class TempDataInCookiesTest : TempDataTestBase, IClassFixture> { - private const int DefaultChunkSize = 4070; - public TempDataInCookiesTest(MvcTestFixture fixture) { Client = fixture.Client; @@ -20,10 +22,10 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests protected override HttpClient Client { get; } [Theory] - [InlineData(DefaultChunkSize)] - [InlineData(DefaultChunkSize * 1.5)] - [InlineData(DefaultChunkSize * 2)] - [InlineData(DefaultChunkSize * 3)] + [InlineData(ChunkingCookieManager.DefaultChunkSize)] + [InlineData(ChunkingCookieManager.DefaultChunkSize * 1.5)] + [InlineData(ChunkingCookieManager.DefaultChunkSize * 2)] + [InlineData(ChunkingCookieManager.DefaultChunkSize * 3)] public async Task RoundTripLargeData_WorksWithChunkingCookies(int size) { // Arrange @@ -35,6 +37,15 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests // Assert 1 Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var cookies = response.Headers.GetValues(HeaderNames.SetCookie); + var cookieTempDataProviderCookies = cookies.Where(cookie => cookie.Contains(CookieTempDataProvider.CookieName)); + Assert.NotNull(cookieTempDataProviderCookies); + + // Verify that all the cookies from CookieTempDataProvider are within the maximum size + foreach (var cookie in cookieTempDataProviderCookies) + { + Assert.True(cookie.Length <= ChunkingCookieManager.DefaultChunkSize); + } // Act 2 response = await Client.SendAsync(GetRequest("/TempData/GetLargeValueFromTempData", response)); diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json index 935f6bdbdb..521939699d 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/project.json @@ -21,6 +21,10 @@ "FiltersWebSite": "1.0.0", "FormatterWebSite": "1.0.0", "HtmlGenerationWebSite": "1.0.0", + "Microsoft.AspNetCore.ChunkingCookieManager.Sources": { + "version": "1.1.0-*", + "type": "build" + }, "Microsoft.AspNetCore.Mvc": "1.1.0-*", "Microsoft.AspNetCore.Mvc.Formatters.Xml": "1.1.0-*", "Microsoft.AspNetCore.Mvc.TestCommon": { diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewFeatures/CookieTempDataProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewFeatures/CookieTempDataProviderTest.cs index 819879e264..ef9b0e2e54 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewFeatures/CookieTempDataProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewFeatures/CookieTempDataProviderTest.cs @@ -6,6 +6,7 @@ using System.Collections; using System.Collections.Generic; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.WebUtilities; using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; using Microsoft.Extensions.Options; @@ -31,19 +32,19 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures } [Fact] - public void LoadTempData_Base64DecodesAnd_UnprotectsData_FromCookie() + public void LoadTempData_Base64UrlDecodesAnd_UnprotectsData_FromCookie() { // Arrange var expectedValues = new Dictionary(); expectedValues.Add("int", 10); var tempDataProviderSerializer = new TempDataSerializer(); var expectedDataToUnprotect = tempDataProviderSerializer.Serialize(expectedValues); - var base64EncodedDataInCookie = Convert.ToBase64String(expectedDataToUnprotect); + var base64AndUrlEncodedDataInCookie = Base64UrlTextEncoder.Encode(expectedDataToUnprotect); var dataProtector = new PassThroughDataProtector(); var tempDataProvider = GetProvider(dataProtector); var requestCookies = new RequestCookieCollection(new Dictionary() { - { CookieTempDataProvider.CookieName, base64EncodedDataInCookie } + { CookieTempDataProvider.CookieName, base64AndUrlEncodedDataInCookie } }); var httpContext = new Mock(); httpContext @@ -59,14 +60,14 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures } [Fact] - public void SaveTempData_ProtectsAnd_Base64EncodesDataAnd_SetsCookie() + public void SaveTempData_ProtectsAnd_Base64UrlEncodesDataAnd_SetsCookie() { // Arrange var values = new Dictionary(); values.Add("int", 10); var tempDataProviderStore = new TempDataSerializer(); var expectedDataToProtect = tempDataProviderStore.Serialize(values); - var expectedDataInCookie = Convert.ToBase64String(expectedDataToProtect); + var expectedDataInCookie = Base64UrlTextEncoder.Encode(expectedDataToProtect); var dataProtector = new PassThroughDataProtector(); var tempDataProvider = GetProvider(dataProtector); var responseCookies = new MockResponseCookieCollection(); @@ -99,7 +100,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures values.Add("int", 10); var tempDataProviderStore = new TempDataSerializer(); var expectedDataToProtect = tempDataProviderStore.Serialize(values); - var expectedDataInCookie = Convert.ToBase64String(expectedDataToProtect); + var expectedDataInCookie = Base64UrlTextEncoder.Encode(expectedDataToProtect); var dataProtector = new PassThroughDataProtector(); var tempDataProvider = GetProvider(dataProtector); var responseCookies = new MockResponseCookieCollection(); @@ -140,7 +141,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures values.Add("int", 10); var tempDataProviderStore = new TempDataSerializer(); var expectedDataToProtect = tempDataProviderStore.Serialize(values); - var expectedDataInCookie = Convert.ToBase64String(expectedDataToProtect); + var expectedDataInCookie = Base64UrlTextEncoder.Encode(expectedDataToProtect); var dataProtector = new PassThroughDataProtector(); var tempDataProvider = GetProvider( dataProtector, @@ -178,12 +179,12 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures values.Add("int", 10); var tempDataProviderStore = new TempDataSerializer(); var serializedData = tempDataProviderStore.Serialize(values); - var base64EncodedData = Convert.ToBase64String(serializedData); + var base64AndUrlEncodedData = Base64UrlTextEncoder.Encode(serializedData); var dataProtector = new PassThroughDataProtector(); var tempDataProvider = GetProvider(dataProtector); var requestCookies = new RequestCookieCollection(new Dictionary() { - { CookieTempDataProvider.CookieName, base64EncodedData } + { CookieTempDataProvider.CookieName, base64AndUrlEncodedData } }); var responseCookies = new MockResponseCookieCollection(); var httpContext = new Mock();