Moves GetCookieValue to an extension method, cleans up code, adds unit tests

This commit is contained in:
Shannon
2017-08-29 10:50:20 +10:00
parent 6bf0d6e175
commit d71b8a139f
4 changed files with 84 additions and 30 deletions

View File

@@ -212,6 +212,7 @@
<Compile Include="Collections\DeepCloneableListTests.cs" />
<Compile Include="Web\Controllers\BackOfficeControllerUnitTests.cs" />
<Compile Include="DelegateExtensionsTests.cs" />
<Compile Include="Web\HttpCookieExtensionsTests.cs" />
<Compile Include="Web\Mvc\RenderIndexActionSelectorAttributeTests.cs" />
<Compile Include="Persistence\Repositories\AuditRepositoryTest.cs" />
<Compile Include="Persistence\Repositories\DomainRepositoryTest.cs" />

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web;
namespace Umbraco.Tests.Web
{
[TestFixture]
public class HttpCookieExtensionsTests
{
[TestCase("hello=world;cookies=are fun;", "hello", "world", true)]
[TestCase("HELlo=world;cookies=are fun", "hello", "world", true)]
[TestCase("HELlo= world;cookies=are fun", "hello", "world", true)]
[TestCase("HELlo =world;cookies=are fun", "hello", "world", true)]
[TestCase("hello = world;cookies=are fun;", "hello", "world", true)]
[TestCase("hellos=world;cookies=are fun", "hello", "world", false)]
[TestCase("hello=world;cookies?=are fun?", "hello", "world", true)]
[TestCase("hel?lo=world;cookies=are fun?", "hel?lo", "world", true)]
public void Get_Cookie_Value_From_HttpRequestHeaders(string cookieHeaderVal, string cookieName, string cookieVal, bool matches)
{
var request = new HttpRequestMessage(HttpMethod.Get, "http://test.com");
var requestHeaders = request.Headers;
requestHeaders.Add("Cookie", cookieHeaderVal);
var valueFromHeader = requestHeaders.GetCookieValue(cookieName);
if (matches)
{
Assert.IsNotNull(valueFromHeader);
Assert.AreEqual(cookieVal, valueFromHeader);
}
else
{
Assert.IsNull(valueFromHeader);
}
}
}
}

View File

@@ -16,6 +16,43 @@ namespace Umbraco.Web
/// </remarks>
internal static class HttpCookieExtensions
{
/// <summary>
/// Retrieves an individual cookie from the cookies collection
/// </summary>
/// <param name="requestHeaders"></param>
/// <param name="cookieName"></param>
/// <returns></returns>
/// <remarks>
/// Adapted from: https://stackoverflow.com/a/29057304/5018 because there's an issue with .NET WebApi cookie parsing logic
/// when using requestHeaders.GetCookies() when an invalid cookie name is present.
/// </remarks>
public static string GetCookieValue(this HttpRequestHeaders requestHeaders, string cookieName)
{
var cookieRequestHeader = requestHeaders
.Where(h => h.Key.Equals("Cookie", StringComparison.InvariantCultureIgnoreCase))
.ToArray();
if (cookieRequestHeader.Length == 0)
return null;
var cookiesHeader = cookieRequestHeader[0];
var cookiesHeaderValue = cookiesHeader.Value.FirstOrDefault();
if (cookiesHeaderValue == null)
return null;
var cookieCollection = cookiesHeaderValue.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
foreach (var cookieNameValue in cookieCollection)
{
var parts = cookieNameValue.Split(new[] {'='}, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2) continue;
if (parts[0].Trim().InvariantEquals(cookieName))
return parts[1].Trim();
}
return null;
}
/// <summary>
/// Removes the cookie from the request and the response if it exists
/// </summary>

View File

@@ -107,41 +107,13 @@ namespace Umbraco.Web.WebApi.Filters
/// <returns></returns>
public static bool ValidateHeaders(HttpRequestHeaders requestHeaders, out string failedReason)
{
var cookieToken = GetCookie(requestHeaders, CsrfValidationCookieName);
var cookieToken = requestHeaders.GetCookieValue(CsrfValidationCookieName);
return ValidateHeaders(
requestHeaders.ToDictionary(x => x.Key, x => x.Value).ToArray(),
cookieToken == null ? null : cookieToken,
out failedReason);
}
/// <summary>
/// Retrieves an individual cookie from the cookies collection
/// Adapted from: https://stackoverflow.com/a/29057304/5018
/// </summary>
/// <param name="requestHeaders"></param>
/// <param name="cookieName"></param>
/// <returns></returns>
private static string GetCookie(HttpRequestHeaders requestHeaders, string cookieName)
{
var cookieRequestHeader = requestHeaders.Where(h => h.Key.Equals("Cookie", StringComparison.InvariantCultureIgnoreCase)).ToArray();
if (cookieRequestHeader.Any() == false)
return null;
var cookiesHeader = cookieRequestHeader.FirstOrDefault();
if (cookiesHeader.Value == null)
return null;
var cookiesHeaderValue = cookiesHeader.Value.FirstOrDefault();
if (cookiesHeaderValue == null)
return null;
var cookieCollection = cookiesHeaderValue.Split(';');
var cookiePair = cookieCollection.FirstOrDefault(c => c.Trim().StartsWith(cookieName, StringComparison.InvariantCultureIgnoreCase));
if (cookiePair == null)
return null;
return cookiePair.Trim().Substring(cookieName.Length + 1);
}
}
}