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, string, string, Exception> _missingRequestToken;
private static readonly Action<ILogger, Exception> _newCookieToken; private static readonly Action<ILogger, Exception> _newCookieToken;
private static readonly Action<ILogger, Exception> _reusedCookieToken; private static readonly Action<ILogger, Exception> _reusedCookieToken;
private static readonly Action<ILogger, Exception> _tokenDeserializeException;
static AntiforgeryLoggerExtensions() static AntiforgeryLoggerExtensions()
{ {
@ -42,6 +43,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
LogLevel.Debug, LogLevel.Debug,
6, 6,
"An antiforgery cookie token was reused."); "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) public static void ValidationFailed(this ILogger logger, string message)
@ -73,5 +78,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
{ {
_reusedCookieToken(logger, null); _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.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -329,15 +328,20 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
try try
{ {
var serializedToken = _tokenStore.GetCookieToken(httpContext); 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 // ignore failures since we'll just generate a new token
return null; _logger.TokenDeserializeException(ex);
} }
return null;
} }
private IAntiforgeryFeature GetTokensInternal(HttpContext httpContext) private IAntiforgeryFeature GetTokensInternal(HttpContext httpContext)

View File

@ -928,6 +928,43 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Times.Never); 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( private DefaultAntiforgery GetAntiforgery(
HttpContext httpContext, HttpContext httpContext,
AntiforgeryOptions options = null, AntiforgeryOptions options = null,
@ -1053,7 +1090,9 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
mockGenerator mockGenerator
.Setup(o => o.GenerateCookieToken()) .Setup(o => o.GenerateCookieToken())
.Returns(useOldCookie ? testTokenSet.OldCookieToken : testTokenSet.NewCookieToken); .Returns(useOldCookie ? testTokenSet.OldCookieToken : testTokenSet.NewCookieToken);
mockGenerator
.Setup(o => o.IsCookieTokenValid(null))
.Returns(false);
mockGenerator mockGenerator
.Setup(o => o.IsCookieTokenValid(testTokenSet.OldCookieToken)) .Setup(o => o.IsCookieTokenValid(testTokenSet.OldCookieToken))
.Returns(isOldCookieValid); .Returns(isOldCookieValid);