Prevent null-ref and log exceptions form Serializer

This commit is contained in:
Ryan Brandenburg 2016-04-18 12:23:48 -07:00
parent fd81151d31
commit eabe83a72d
3 changed files with 59 additions and 6 deletions

View File

@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
private static readonly Action<ILogger, string, string, Exception> _missingRequestToken;
private static readonly Action<ILogger, Exception> _newCookieToken;
private static readonly Action<ILogger, Exception> _reusedCookieToken;
private static readonly Action<ILogger, Exception> _tokenDeserializeException;
static AntiforgeryLoggerExtensions()
{
@ -42,6 +43,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
LogLevel.Debug,
6,
"An antiforgery cookie token was reused.");
_tokenDeserializeException = LoggerMessage.Define(
LogLevel.Error,
7,
"An exception was thrown while deserializing the token.");
}
public static void ValidationFailed(this ILogger logger, string message)
@ -73,5 +78,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
{
_reusedCookieToken(logger, null);
}
public static void TokenDeserializeException(this ILogger logger, Exception exception)
{
_tokenDeserializeException(logger, exception);
}
}
}

View File

@ -5,7 +5,6 @@ using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -329,15 +328,20 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
try
{
var serializedToken = _tokenStore.GetCookieToken(httpContext);
var token = _tokenSerializer.Deserialize(serializedToken);
return token;
if (serializedToken != null)
{
var token = _tokenSerializer.Deserialize(serializedToken);
return token;
}
}
catch
catch (Exception ex)
{
// ignore failures since we'll just generate a new token
return null;
_logger.TokenDeserializeException(ex);
}
return null;
}
private IAntiforgeryFeature GetTokensInternal(HttpContext httpContext)

View File

@ -928,6 +928,43 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Times.Never);
}
[Fact]
public void SetCookieTokenAndHeader_NullCookieToken()
{
// 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);
// Act
antiforgery.SetCookieTokenAndHeader(context.HttpContext);
// Assert
context.TokenSerializer.Verify(s => s.Deserialize(null), Times.Never);
}
private DefaultAntiforgery GetAntiforgery(
HttpContext httpContext,
AntiforgeryOptions options = null,
@ -1053,7 +1090,9 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
mockGenerator
.Setup(o => o.GenerateCookieToken())
.Returns(useOldCookie ? testTokenSet.OldCookieToken : testTokenSet.NewCookieToken);
mockGenerator
.Setup(o => o.IsCookieTokenValid(null))
.Returns(false);
mockGenerator
.Setup(o => o.IsCookieTokenValid(testTokenSet.OldCookieToken))
.Returns(isOldCookieValid);