Moves GetCookieValue to an extension method, cleans up code, adds unit tests
This commit is contained in:
@@ -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" />
|
||||
|
||||
44
src/Umbraco.Tests/Web/HttpCookieExtensionsTests.cs
Normal file
44
src/Umbraco.Tests/Web/HttpCookieExtensionsTests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user