* Add logging to Antiforgery
This commit is contained in:
parent
08cf13b870
commit
c8a9ecc0c1
|
|
@ -0,0 +1,77 @@
|
|||
// 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;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||
{
|
||||
internal static class AntiforgeryLoggerExtensions
|
||||
{
|
||||
private static readonly Action<ILogger, string, Exception> _validationFailed;
|
||||
private static readonly Action<ILogger, Exception> _validated;
|
||||
private static readonly Action<ILogger, string, Exception> _missingCookieToken;
|
||||
private static readonly Action<ILogger, string, string, Exception> _missingRequestToken;
|
||||
private static readonly Action<ILogger, Exception> _newCookieToken;
|
||||
private static readonly Action<ILogger, Exception> _reusedCookieToken;
|
||||
|
||||
static AntiforgeryLoggerExtensions()
|
||||
{
|
||||
_validationFailed = LoggerMessage.Define<string>(
|
||||
LogLevel.Warning,
|
||||
1,
|
||||
"Antiforgery validation failed with message '{Message}'.");
|
||||
_validated = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
2,
|
||||
"Antiforgery successfully validated a request.");
|
||||
_missingCookieToken = LoggerMessage.Define<string>(
|
||||
LogLevel.Warning,
|
||||
3,
|
||||
"The required antiforgery cookie '{CookieName}' is not present.");
|
||||
_missingRequestToken = LoggerMessage.Define<string, string>(
|
||||
LogLevel.Warning,
|
||||
4,
|
||||
"The required antiforgery request token was not provided in either form field '{FormFieldName}' "
|
||||
+ "or header '{HeaderName}'.");
|
||||
_newCookieToken = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
5,
|
||||
"A new antiforgery cookie token was created.");
|
||||
_reusedCookieToken = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
6,
|
||||
"An antiforgery cookie token was reused.");
|
||||
}
|
||||
|
||||
public static void ValidationFailed(this ILogger logger, string message)
|
||||
{
|
||||
_validationFailed(logger, message, null);
|
||||
}
|
||||
|
||||
public static void ValidatedAntiforgeryToken(this ILogger logger)
|
||||
{
|
||||
_validated(logger, null);
|
||||
}
|
||||
|
||||
public static void MissingCookieToken(this ILogger logger, string cookieName)
|
||||
{
|
||||
_missingCookieToken(logger, cookieName, null);
|
||||
}
|
||||
|
||||
public static void MissingRequestToken(this ILogger logger, string formFieldName, string headerName)
|
||||
{
|
||||
_missingRequestToken(logger, formFieldName, headerName, null);
|
||||
}
|
||||
|
||||
public static void NewCookieToken(this ILogger logger)
|
||||
{
|
||||
_newCookieToken(logger, null);
|
||||
}
|
||||
|
||||
public static void ReusedCookieToken(this ILogger logger)
|
||||
{
|
||||
_reusedCookieToken(logger, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||
|
|
@ -19,17 +20,20 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
private readonly IAntiforgeryTokenGenerator _tokenGenerator;
|
||||
private readonly IAntiforgeryTokenSerializer _tokenSerializer;
|
||||
private readonly IAntiforgeryTokenStore _tokenStore;
|
||||
private readonly ILogger<DefaultAntiforgery> _logger;
|
||||
|
||||
public DefaultAntiforgery(
|
||||
IOptions<AntiforgeryOptions> antiforgeryOptionsAccessor,
|
||||
IAntiforgeryTokenGenerator tokenGenerator,
|
||||
IAntiforgeryTokenSerializer tokenSerializer,
|
||||
IAntiforgeryTokenStore tokenStore)
|
||||
IAntiforgeryTokenStore tokenStore,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
_options = antiforgeryOptionsAccessor.Value;
|
||||
_tokenGenerator = tokenGenerator;
|
||||
_tokenSerializer = tokenSerializer;
|
||||
_tokenStore = tokenStore;
|
||||
_logger = loggerFactory.CreateLogger<DefaultAntiforgery>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -46,6 +50,11 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
if (tokenSet.IsNewCookieToken)
|
||||
{
|
||||
SaveCookieTokenAndHeader(httpContext, tokenSet.CookieToken);
|
||||
_logger.NewCookieToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.ReusedCookieToken();
|
||||
}
|
||||
|
||||
return Serialize(tokenSet);
|
||||
|
|
@ -76,8 +85,14 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
CheckSSLConfig(httpContext);
|
||||
|
||||
var tokens = await _tokenStore.GetRequestTokensAsync(httpContext);
|
||||
if (tokens.CookieToken == null || tokens.RequestToken == null)
|
||||
if (tokens.CookieToken == null)
|
||||
{
|
||||
_logger.MissingCookieToken(_options.CookieName);
|
||||
return false;
|
||||
}
|
||||
if (tokens.RequestToken == null)
|
||||
{
|
||||
_logger.MissingRequestToken(_options.FormFieldName, _options.HeaderName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -87,11 +102,22 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
|
||||
// Validate
|
||||
string message;
|
||||
return _tokenGenerator.TryValidateTokenSet(
|
||||
var result = _tokenGenerator.TryValidateTokenSet(
|
||||
httpContext,
|
||||
deserializedCookieToken,
|
||||
deserializedRequestToken,
|
||||
out message);
|
||||
|
||||
if (result)
|
||||
{
|
||||
_logger.ValidatedAntiforgeryToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.ValidationFailed(message);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -133,6 +159,8 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
}
|
||||
|
||||
ValidateTokens(httpContext, tokens);
|
||||
|
||||
_logger.ValidatedAntiforgeryToken();
|
||||
}
|
||||
|
||||
private void ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ using System.Security.Claims;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -18,13 +21,12 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
public async Task ChecksSSL_ValidateRequestAsync_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpContext = GetHttpContext();
|
||||
var options = new AntiforgeryOptions()
|
||||
{
|
||||
RequireSsl = true
|
||||
};
|
||||
|
||||
var antiforgery = GetAntiforgery(options);
|
||||
var antiforgery = GetAntiforgery(httpContext, options);
|
||||
|
||||
// Act & Assert
|
||||
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
|
|
@ -39,13 +41,13 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
public async Task ChecksSSL_IsRequestValidAsync_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpContext = GetHttpContext();
|
||||
var options = new AntiforgeryOptions()
|
||||
{
|
||||
RequireSsl = true
|
||||
};
|
||||
|
||||
var antiforgery = GetAntiforgery(options);
|
||||
var antiforgery = GetAntiforgery(httpContext, options);
|
||||
|
||||
// Act & Assert
|
||||
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
|
|
@ -60,13 +62,13 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
public void ChecksSSL_GetAndStoreTokens_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpContext = GetHttpContext();
|
||||
var options = new AntiforgeryOptions()
|
||||
{
|
||||
RequireSsl = true
|
||||
};
|
||||
|
||||
var antiforgery = GetAntiforgery(options);
|
||||
var antiforgery = GetAntiforgery(httpContext, options);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(
|
||||
|
|
@ -81,13 +83,13 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
public void ChecksSSL_GetTokens_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpContext = GetHttpContext();
|
||||
var options = new AntiforgeryOptions()
|
||||
{
|
||||
RequireSsl = true
|
||||
};
|
||||
|
||||
var antiforgery = GetAntiforgery(options);
|
||||
var antiforgery = GetAntiforgery(httpContext, options);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(
|
||||
|
|
@ -102,13 +104,13 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
public void ChecksSSL_SetCookieTokenAndHeader_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpContext = GetHttpContext();
|
||||
var options = new AntiforgeryOptions()
|
||||
{
|
||||
RequireSsl = true
|
||||
};
|
||||
|
||||
var antiforgery = GetAntiforgery(options);
|
||||
var antiforgery = GetAntiforgery(httpContext, options);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(
|
||||
|
|
@ -290,12 +292,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
out message))
|
||||
.Returns(false)
|
||||
.Verifiable();
|
||||
|
||||
var antiforgery = new DefaultAntiforgery(
|
||||
new TestOptionsManager(),
|
||||
context.TokenGenerator.Object,
|
||||
context.TokenSerializer.Object,
|
||||
context.TokenStore.Object);
|
||||
var antiforgery = GetAntiforgery(context);
|
||||
|
||||
// Act & assert
|
||||
var exception = await Assert.ThrowsAsync<AntiforgeryValidationException>(
|
||||
|
|
@ -458,6 +455,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
}
|
||||
|
||||
private DefaultAntiforgery GetAntiforgery(
|
||||
HttpContext httpContext,
|
||||
AntiforgeryOptions options = null,
|
||||
IAntiforgeryTokenGenerator tokenGenerator = null,
|
||||
IAntiforgeryTokenSerializer tokenSerializer = null,
|
||||
|
|
@ -469,16 +467,29 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
optionsManager.Value = options;
|
||||
}
|
||||
|
||||
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
||||
return new DefaultAntiforgery(
|
||||
antiforgeryOptionsAccessor: optionsManager,
|
||||
tokenGenerator: tokenGenerator,
|
||||
tokenSerializer: tokenSerializer,
|
||||
tokenStore: tokenStore);
|
||||
tokenStore: tokenStore,
|
||||
loggerFactory: loggerFactory);
|
||||
}
|
||||
|
||||
private IServiceProvider GetServices()
|
||||
{
|
||||
var builder = new ServiceCollection();
|
||||
builder.AddSingleton<ILoggerFactory>(new LoggerFactory());
|
||||
|
||||
return builder.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private HttpContext GetHttpContext()
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
||||
httpContext.RequestServices = GetServices();
|
||||
|
||||
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("some-auth"));
|
||||
return httpContext;
|
||||
}
|
||||
|
|
@ -486,6 +497,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
private DefaultAntiforgery GetAntiforgery(AntiforgeryMockContext context)
|
||||
{
|
||||
return GetAntiforgery(
|
||||
context.HttpContext,
|
||||
context.Options,
|
||||
context.TokenGenerator?.Object,
|
||||
context.TokenSerializer?.Object,
|
||||
|
|
@ -630,4 +642,4 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
public AntiforgeryOptions Value { get; set; } = new AntiforgeryOptions();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"Microsoft.AspNetCore.Http": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Testing": "1.0.0-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
||||
"Microsoft.Extensions.Logging": "1.0.0-*",
|
||||
"Microsoft.Extensions.WebEncoders": "1.0.0-*",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
||||
"xunit": "2.1.0-*"
|
||||
|
|
@ -19,7 +20,7 @@
|
|||
"frameworks": {
|
||||
"dnx451": {
|
||||
"frameworkAssemblies": {
|
||||
"System.Threading.Tasks": ""
|
||||
"System.Threading.Tasks": ""
|
||||
},
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
|
|||
Loading…
Reference in New Issue