Changed RequestSizeLimitAttribute to create an authorization filter rather than a resource filter.
[Fixes #6777] RequestSizeLimit is ignored
This commit is contained in:
parent
de38922601
commit
06f6de6c11
|
|
@ -199,10 +199,10 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
ServiceDescriptor.Singleton<IFilterProvider, DefaultFilterProvider>());
|
||||
|
||||
//
|
||||
// Resource Filters
|
||||
// RequestSizeLimit filters
|
||||
//
|
||||
services.TryAddTransient<RequestSizeLimitResourceFilter>();
|
||||
services.TryAddTransient<DisableRequestSizeLimitResourceFilter>();
|
||||
services.TryAddTransient<RequestSizeLimitFilter>();
|
||||
services.TryAddTransient<DisableRequestSizeLimitFilter>();
|
||||
|
||||
//
|
||||
// ModelBinding, Validation
|
||||
|
|
|
|||
|
|
@ -14,8 +14,23 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class DisableRequestSizeLimitAttribute : Attribute, IFilterFactory, IOrderedFilter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int Order { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the order value for determining the order of execution of filters. Filters execute in
|
||||
/// ascending numeric value of the <see cref="Order"/> property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Filters are executed in an ordering determined by an ascending sort of the <see cref="Order"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The default Order for this attribute is 900 because it must run before ValidateAntiForgeryTokenAttribute and
|
||||
/// after any filter which does authentication or login in order to allow them to behave as expected (ie Unauthenticated or Redirect instead of 400).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Look at <see cref="IOrderedFilter.Order"/> for more detailed info.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public int Order { get; set; } = 900;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
|
|
@ -23,7 +38,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
var filter = serviceProvider.GetRequiredService<DisableRequestSizeLimitResourceFilter>();
|
||||
var filter = serviceProvider.GetRequiredService<DisableRequestSizeLimitFilter>();
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,34 +14,26 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
/// A filter that sets <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/>
|
||||
/// to <c>null</c>.
|
||||
/// </summary>
|
||||
public class DisableRequestSizeLimitResourceFilter : IResourceFilter, IRequestSizePolicy
|
||||
public class DisableRequestSizeLimitFilter : IAuthorizationFilter, IRequestSizePolicy
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="DisableRequestSizeLimitResourceFilter"/>.
|
||||
/// Creates a new instance of <see cref="DisableRequestSizeLimitFilter"/>.
|
||||
/// </summary>
|
||||
public DisableRequestSizeLimitResourceFilter(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<DisableRequestSizeLimitResourceFilter>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Order { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
public DisableRequestSizeLimitFilter(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<DisableRequestSizeLimitFilter>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/>
|
||||
/// to <c>null</c>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ResourceExecutingContext"/>.</param>
|
||||
/// <param name="context">The <see cref="AuthorizationFilterContext"/>.</param>
|
||||
/// <remarks>If <see cref="IHttpMaxRequestBodySizeFeature"/> is not enabled or is read-only,
|
||||
/// the <see cref="DisableRequestSizeLimitAttribute"/> is not applied.</remarks>
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
public void OnAuthorization(AuthorizationFilterContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -14,32 +14,27 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
/// A filter that sets the <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/>
|
||||
/// to the specified <see cref="Bytes"/>.
|
||||
/// </summary>
|
||||
public class RequestSizeLimitResourceFilter : IResourceFilter, IRequestSizePolicy
|
||||
public class RequestSizeLimitFilter : IAuthorizationFilter, IRequestSizePolicy
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RequestSizeLimitResourceFilter"/>.
|
||||
/// Creates a new instance of <see cref="RequestSizeLimitFilter"/>.
|
||||
/// </summary>
|
||||
public RequestSizeLimitResourceFilter(ILoggerFactory loggerFactory)
|
||||
public RequestSizeLimitFilter(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<RequestSizeLimitResourceFilter>();
|
||||
_logger = loggerFactory.CreateLogger<RequestSizeLimitFilter>();
|
||||
}
|
||||
|
||||
public long Bytes { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/> to <see cref="Bytes"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ResourceExecutingContext"/>.</param>
|
||||
/// <param name="context">The <see cref="AuthorizationFilterContext"/>.</param>
|
||||
/// <remarks>If <see cref="IHttpMaxRequestBodySizeFeature"/> is not enabled or is read-only,
|
||||
/// the <see cref="RequestSizeLimitAttribute"/> is not applied.</remarks>
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
public void OnAuthorization(AuthorizationFilterContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -25,8 +25,23 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
_bytes = bytes;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Order { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the order value for determining the order of execution of filters. Filters execute in
|
||||
/// ascending numeric value of the <see cref="Order"/> property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Filters are executed in an ordering determined by an ascending sort of the <see cref="Order"/> property.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The default Order for this attribute is 900 because it must run before ValidateAntiForgeryTokenAttribute and
|
||||
/// after any filter which does authentication or login in order to allow them to behave as expected (ie Unauthenticated or Redirect instead of 400).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Look at <see cref="IOrderedFilter.Order"/> for more detailed info.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public int Order { get; set; } = 900;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
|
|
@ -34,7 +49,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
var filter = serviceProvider.GetRequiredService<RequestSizeLimitResourceFilter>();
|
||||
var filter = serviceProvider.GetRequiredService<RequestSizeLimitFilter>();
|
||||
filter.Bytes = _bytes;
|
||||
return filter;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
|
|
@ -14,20 +12,20 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class DisableRequestSizeLimitResourceFilterTest
|
||||
public class DisableRequestSizeLimitFilterTest
|
||||
{
|
||||
[Fact]
|
||||
public void SetsMaxRequestBodySizeToNull()
|
||||
{
|
||||
// Arrange
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitFilter(NullLoggerFactory.Instance);
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
disableRequestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
|
|
@ -37,16 +35,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
public void SkipsWhenOverridden()
|
||||
{
|
||||
// Arrange
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var disableRequestSizeLimitResourceFilterFinal = new DisableRequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter, disableRequestSizeLimitResourceFilterFinal });
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitFilter(NullLoggerFactory.Instance);
|
||||
var disableRequestSizeLimitResourceFilterFinal = new DisableRequestSizeLimitFilter(NullLoggerFactory.Instance);
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(
|
||||
new IFilterMetadata[] { disableRequestSizeLimitResourceFilter, disableRequestSizeLimitResourceFilterFinal });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
disableRequestSizeLimitResourceFilterFinal.OnResourceExecuting(resourceExecutingContext);
|
||||
disableRequestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
disableRequestSizeLimitResourceFilterFinal.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
|
|
@ -60,11 +59,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(loggerFactory);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitFilter(loggerFactory);
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
disableRequestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
|
|
@ -79,15 +78,15 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(loggerFactory);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitFilter(loggerFactory);
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
httpMaxRequestBodySize.IsReadOnly = true;
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
disableRequestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
|
|
@ -101,26 +100,23 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(loggerFactory);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitFilter(loggerFactory);
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
disableRequestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"The request body size limit has been disabled.", write.State.ToString());
|
||||
}
|
||||
|
||||
private static ResourceExecutingContext CreateResourceExecutingContext(IFilterMetadata[] filters)
|
||||
private static AuthorizationFilterContext CreateauthorizationFilterContext(IFilterMetadata[] filters)
|
||||
{
|
||||
return new ResourceExecutingContext(
|
||||
CreateActionContext(),
|
||||
filters,
|
||||
new List<IValueProviderFactory>());
|
||||
return new AuthorizationFilterContext(CreateActionContext(), filters);
|
||||
}
|
||||
|
||||
private static ActionContext CreateActionContext()
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
|
|
@ -14,21 +12,21 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class RequestSizeLimitResourceFilterTest
|
||||
public class RequestSizeLimitFilterTest
|
||||
{
|
||||
[Fact]
|
||||
public void SetsMaxRequestBodySize()
|
||||
{
|
||||
// Arrange
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitFilter(NullLoggerFactory.Instance);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
requestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12345, httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
|
|
@ -38,18 +36,19 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
public void SkipsWhenOverridden()
|
||||
{
|
||||
// Arrange
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitFilter(NullLoggerFactory.Instance);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var requestSizeLimitResourceFilterFinal = new RequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var requestSizeLimitResourceFilterFinal = new RequestSizeLimitFilter(NullLoggerFactory.Instance);
|
||||
requestSizeLimitResourceFilterFinal.Bytes = 0;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter, requestSizeLimitResourceFilterFinal });
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(
|
||||
new IFilterMetadata[] { requestSizeLimitResourceFilter, requestSizeLimitResourceFilterFinal });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
requestSizeLimitResourceFilterFinal.OnResourceExecuting(resourceExecutingContext);
|
||||
requestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
requestSizeLimitResourceFilterFinal.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
|
|
@ -63,12 +62,12 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(loggerFactory);
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitFilter(loggerFactory);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
requestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
|
|
@ -83,16 +82,16 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(loggerFactory);
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitFilter(loggerFactory);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
httpMaxRequestBodySize.IsReadOnly = true;
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
requestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
|
|
@ -106,27 +105,24 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(loggerFactory);
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitFilter(loggerFactory);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
var authorizationFilterContext = CreateauthorizationFilterContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
authorizationFilterContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
requestSizeLimitResourceFilter.OnAuthorization(authorizationFilterContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"The maximum request body size has been set to 12345.", write.State.ToString());
|
||||
}
|
||||
|
||||
private static ResourceExecutingContext CreateResourceExecutingContext(IFilterMetadata[] filters)
|
||||
private static AuthorizationFilterContext CreateauthorizationFilterContext(IFilterMetadata[] filters)
|
||||
{
|
||||
return new ResourceExecutingContext(
|
||||
CreateActionContext(),
|
||||
filters,
|
||||
new List<IValueProviderFactory>());
|
||||
return new AuthorizationFilterContext(CreateActionContext(), filters);
|
||||
}
|
||||
|
||||
private static ActionContext CreateActionContext()
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class RequestSizeLimitTest : IClassFixture<MvcTestFixture<BasicWebSite.StartupRequestLimitSize>>
|
||||
{
|
||||
// Some tests require comparing the actual response body against an expected response baseline
|
||||
// so they require a reference to the assembly on which the resources are located, in order to
|
||||
// make the tests less verbose, we get a reference to the assembly with the resources and we
|
||||
// use it on all the rest of the tests.
|
||||
private static readonly Assembly _resourcesAssembly = typeof(BasicTests).GetTypeInfo().Assembly;
|
||||
|
||||
public RequestSizeLimitTest(MvcTestFixture<BasicWebSite.StartupRequestLimitSize> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task RequestSizeLimitCheckHappens_BeforeAntiforgeryTokenValidation()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage();
|
||||
var kvps = new List<KeyValuePair<string, string>>();
|
||||
kvps.Add(new KeyValuePair<string, string>("SampleString", new string('p', 1024)));
|
||||
kvps.Add(new KeyValuePair<string, string>("RequestVerificationToken", "invalid-data"));
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(
|
||||
"RequestSizeLimit/RequestSizeLimitCheckBeforeAntiforgeryValidation",
|
||||
new FormUrlEncodedContent(kvps));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||
var result = await response.Content.ReadAsStringAsync();
|
||||
Assert.Contains(
|
||||
"InvalidOperationException: Request content size is greater than the limit size",
|
||||
result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AntiforgeryTokenValidationHappens_AfterRequestSizeLimitCheck()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage();
|
||||
var kvps = new List<KeyValuePair<string, string>>();
|
||||
kvps.Add(new KeyValuePair<string, string>("SampleString", "string"));
|
||||
kvps.Add(new KeyValuePair<string, string>("RequestVerificationToken", "invalid-data"));
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(
|
||||
"RequestSizeLimit/RequestSizeLimitCheckBeforeAntiforgeryValidation",
|
||||
new FormUrlEncodedContent(kvps));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisableRequestSizeLimitOnAction_OverridesControllerLevelSettings()
|
||||
{
|
||||
// Arrange
|
||||
var expected = $"{{\"sampleInt\":10,\"sampleString\":\"{new string('p', 1024)}\"}}";
|
||||
var request = new HttpRequestMessage();
|
||||
request.Method = HttpMethod.Post;
|
||||
request.Content = new StringContent(expected, Encoding.UTF8, "text/json");
|
||||
request.RequestUri = new Uri("http://localhost/RequestSizeLimit/DisableRequestSizeLimit");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var actual = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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 BasicWebSite.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace BasicWebSite.Controllers
|
||||
{
|
||||
[RequestSizeLimit(500)]
|
||||
public class RequestSizeLimitController : Controller
|
||||
{
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult RequestSizeLimitCheckBeforeAntiforgeryValidation(Product product)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
return Json(product);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[DisableRequestSizeLimit]
|
||||
public IActionResult DisableRequestSizeLimit([FromBody] Product product)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
return Json(product);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// 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 System.IO;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BasicWebSite
|
||||
{
|
||||
public class StartupRequestLimitSize
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
||||
app.Use((httpContext, next) =>
|
||||
{
|
||||
var testHttpMaxRequestBodySizeFeature = new TestHttpMaxRequestBodySizeFeature();
|
||||
httpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(
|
||||
testHttpMaxRequestBodySizeFeature);
|
||||
|
||||
httpContext.Request.Body = new RequestBodySizeCheckingStream(
|
||||
httpContext.Request.Body,
|
||||
testHttpMaxRequestBodySizeFeature);
|
||||
|
||||
return next();
|
||||
});
|
||||
|
||||
app.UseMvcWithDefaultRoute();
|
||||
}
|
||||
|
||||
private class RequestBodySizeCheckingStream : Stream
|
||||
{
|
||||
private readonly Stream _innerStream;
|
||||
private readonly IHttpMaxRequestBodySizeFeature _maxRequestBodySizeFeature;
|
||||
|
||||
public RequestBodySizeCheckingStream(
|
||||
Stream innerStream,
|
||||
IHttpMaxRequestBodySizeFeature maxRequestBodySizeFeature)
|
||||
{
|
||||
_innerStream = innerStream;
|
||||
_maxRequestBodySizeFeature = maxRequestBodySizeFeature;
|
||||
}
|
||||
public override bool CanRead => _innerStream.CanRead;
|
||||
|
||||
public override bool CanSeek => _innerStream.CanSeek;
|
||||
|
||||
public override bool CanWrite => _innerStream.CanWrite;
|
||||
|
||||
public override long Length => _innerStream.Length;
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { return _innerStream.Position; }
|
||||
set { _innerStream.Position = value; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
_innerStream.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (_maxRequestBodySizeFeature.MaxRequestBodySize != null
|
||||
&& _innerStream.Length > _maxRequestBodySizeFeature.MaxRequestBodySize)
|
||||
{
|
||||
throw new InvalidOperationException("Request content size is greater than the limit size");
|
||||
}
|
||||
|
||||
return _innerStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return _innerStream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
_innerStream.SetLength(value);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
_innerStream.Write(buffer, offset, count);
|
||||
}
|
||||
}
|
||||
|
||||
private class TestHttpMaxRequestBodySizeFeature : IHttpMaxRequestBodySizeFeature
|
||||
{
|
||||
public bool IsReadOnly => false;
|
||||
public long? MaxRequestBodySize { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue