Add support for clients to configure a policy with custom logic about whether an origin should be allowed and provide a default implementation of the functionality to allow wildcard subdomains
This commit is contained in:
parent
2d916a8b48
commit
8214954d5b
|
|
@ -37,3 +37,4 @@ node_modules
|
|||
*launchSettings.json
|
||||
.build/
|
||||
.testPublish/
|
||||
.vscode
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||
|
|
@ -14,6 +15,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
{
|
||||
private TimeSpan? _preflightMaxAge;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor for a CorsPolicy.
|
||||
/// </summary>
|
||||
public CorsPolicy()
|
||||
{
|
||||
IsOriginAllowed = DefaultIsOriginAllowed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if all headers are allowed.
|
||||
/// </summary>
|
||||
|
|
@ -62,6 +71,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a function which evaluates whether an origin is allowed.
|
||||
/// </summary>
|
||||
public Func<string, bool> IsOriginAllowed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers that the resource might use and can be exposed.
|
||||
/// </summary>
|
||||
|
|
@ -141,5 +155,10 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
builder.Append("}");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private bool DefaultIsOriginAllowed(string origin)
|
||||
{
|
||||
return Origins.Contains(origin, StringComparer.Ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// Adds the specified <paramref name="origins"/> to the policy.
|
||||
/// </summary>
|
||||
/// <param name="origins">The origins that are allowed.</param>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder WithOrigins(params string[] origins)
|
||||
{
|
||||
foreach (var req in origins)
|
||||
|
|
@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// Adds the specified <paramref name="headers"/> to the policy.
|
||||
/// </summary>
|
||||
/// <param name="headers">The headers which need to be allowed in the request.</param>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder WithHeaders(params string[] headers)
|
||||
{
|
||||
foreach (var req in headers)
|
||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// Adds the specified <paramref name="exposedHeaders"/> to the policy.
|
||||
/// </summary>
|
||||
/// <param name="exposedHeaders">The headers which need to be exposed to the client.</param>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder WithExposedHeaders(params string[] exposedHeaders)
|
||||
{
|
||||
foreach (var req in exposedHeaders)
|
||||
|
|
@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// Adds the specified <paramref name="methods"/> to the policy.
|
||||
/// </summary>
|
||||
/// <param name="methods">The methods which need to be added to the policy.</param>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder WithMethods(params string[] methods)
|
||||
{
|
||||
foreach (var req in methods)
|
||||
|
|
@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// <summary>
|
||||
/// Sets the policy to allow credentials.
|
||||
/// </summary>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder AllowCredentials()
|
||||
{
|
||||
_policy.SupportsCredentials = true;
|
||||
|
|
@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// <summary>
|
||||
/// Sets the policy to not allow credentials.
|
||||
/// </summary>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder DisallowCredentials()
|
||||
{
|
||||
_policy.SupportsCredentials = false;
|
||||
|
|
@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// <summary>
|
||||
/// Ensures that the policy allows any origin.
|
||||
/// </summary>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder AllowAnyOrigin()
|
||||
{
|
||||
_policy.Origins.Clear();
|
||||
|
|
@ -124,7 +124,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// <summary>
|
||||
/// Ensures that the policy allows any method.
|
||||
/// </summary>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder AllowAnyMethod()
|
||||
{
|
||||
_policy.Methods.Clear();
|
||||
|
|
@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// <summary>
|
||||
/// Ensures that the policy allows any header.
|
||||
/// </summary>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder AllowAnyHeader()
|
||||
{
|
||||
_policy.Headers.Clear();
|
||||
|
|
@ -148,13 +148,36 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// </summary>
|
||||
/// <param name="preflightMaxAge">A positive <see cref="TimeSpan"/> indicating the time a preflight
|
||||
/// request can be cached.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder SetPreflightMaxAge(TimeSpan preflightMaxAge)
|
||||
{
|
||||
_policy.PreflightMaxAge = preflightMaxAge;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified <paramref name="isOriginAllowed"/> for the underlying policy.
|
||||
/// </summary>
|
||||
/// <param name="isOriginAllowed">The function used by the policy to evaluate if an origin is allowed.</param>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder SetIsOriginAllowed(Func<string, bool> isOriginAllowed)
|
||||
{
|
||||
_policy.IsOriginAllowed = isOriginAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="CorsPolicy.IsOriginAllowed"/> property of the policy to be a function
|
||||
/// that allows origins to match a configured wildcarded domain when evaluating if the
|
||||
/// origin is allowed.
|
||||
/// </summary>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
public CorsPolicyBuilder SetIsOriginAllowedToAllowWildcardSubdomains()
|
||||
{
|
||||
_policy.IsOriginAllowed = _policy.IsOriginAnAllowedSubdomain;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a new <see cref="CorsPolicy"/> using the entries added.
|
||||
/// </summary>
|
||||
|
|
@ -168,7 +191,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// Combines the given <paramref name="policy"/> to the existing properties in the builder.
|
||||
/// </summary>
|
||||
/// <param name="policy">The policy which needs to be combined.</param>
|
||||
/// <returns>The current policy builder</returns>
|
||||
/// <returns>The current policy builder.</returns>
|
||||
private CorsPolicyBuilder Combine(CorsPolicy policy)
|
||||
{
|
||||
if (policy == null)
|
||||
|
|
@ -180,6 +203,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
WithHeaders(policy.Headers.ToArray());
|
||||
WithExposedHeaders(policy.ExposedHeaders.ToArray());
|
||||
WithMethods(policy.Methods.ToArray());
|
||||
SetIsOriginAllowed(policy.IsOriginAllowed);
|
||||
|
||||
if (policy.PreflightMaxAge.HasValue)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// 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.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||
{
|
||||
internal static class CorsPolicyExtensions
|
||||
{
|
||||
private const string _WildcardSubdomain = "*.";
|
||||
|
||||
public static bool IsOriginAnAllowedSubdomain(this CorsPolicy policy, string origin)
|
||||
{
|
||||
if (policy.Origins.Contains(origin))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var originUri = new Uri(origin, UriKind.Absolute);
|
||||
return policy.Origins
|
||||
.Where(o => o.Contains($"://{_WildcardSubdomain}"))
|
||||
.Select(CreateDomainUri)
|
||||
.Any(domain => UriHelpers.IsSubdomainOf(originUri, domain));
|
||||
}
|
||||
|
||||
private static Uri CreateDomainUri(string origin)
|
||||
{
|
||||
return new Uri(origin.Replace(_WildcardSubdomain, string.Empty), UriKind.Absolute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,17 +97,8 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
|
||||
{
|
||||
var origin = context.Request.Headers[CorsConstants.Origin];
|
||||
if (StringValues.IsNullOrEmpty(origin))
|
||||
if (!IsOriginAllowed(policy, origin))
|
||||
{
|
||||
_logger?.RequestDoesNotHaveOriginHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
_logger?.RequestHasOriginHeader(origin);
|
||||
if (!policy.AllowAnyOrigin && !policy.Origins.Contains(origin))
|
||||
{
|
||||
_logger?.PolicyFailure();
|
||||
_logger?.OriginNotAllowed(origin);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -120,17 +111,8 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result)
|
||||
{
|
||||
var origin = context.Request.Headers[CorsConstants.Origin];
|
||||
if (StringValues.IsNullOrEmpty(origin))
|
||||
if (!IsOriginAllowed(policy, origin))
|
||||
{
|
||||
_logger?.RequestDoesNotHaveOriginHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
_logger?.RequestHasOriginHeader(origin);
|
||||
if (!policy.AllowAnyOrigin && !policy.Origins.Contains(origin))
|
||||
{
|
||||
_logger?.PolicyFailure();
|
||||
_logger?.OriginNotAllowed(origin);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +268,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
result.AllowedOrigin = CorsConstants.AnyOrigin;
|
||||
}
|
||||
}
|
||||
else if (policy.Origins.Contains(origin))
|
||||
else if (policy.IsOriginAllowed(origin))
|
||||
{
|
||||
result.AllowedOrigin = origin;
|
||||
}
|
||||
|
|
@ -304,5 +286,23 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
target.Add(current);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsOriginAllowed(CorsPolicy policy, StringValues origin)
|
||||
{
|
||||
if (StringValues.IsNullOrEmpty(origin))
|
||||
{
|
||||
_logger?.RequestDoesNotHaveOriginHeader();
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger?.RequestHasOriginHeader(origin);
|
||||
if (policy.AllowAnyOrigin || policy.IsOriginAllowed(origin))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
_logger?.PolicyFailure();
|
||||
_logger?.OriginNotAllowed(origin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||
{
|
||||
internal static class UriHelpers
|
||||
{
|
||||
public static bool IsSubdomainOf(Uri subdomain, Uri domain)
|
||||
{
|
||||
return subdomain.IsAbsoluteUri
|
||||
&& domain.IsAbsoluteUri
|
||||
&& subdomain.Scheme == domain.Scheme
|
||||
&& subdomain.Port == domain.Port
|
||||
&& subdomain.Host.EndsWith($".{domain.Host}", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-US")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation.")]
|
||||
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
|
||||
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Cors.Test,PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
public void Constructor_WithPolicy_AddsTheGivenPolicy()
|
||||
{
|
||||
// Arrange
|
||||
Func<string, bool> isOriginAllowed = origin => true;
|
||||
var originalPolicy = new CorsPolicy();
|
||||
originalPolicy.Origins.Add("http://existing.com");
|
||||
originalPolicy.Headers.Add("Existing");
|
||||
|
|
@ -21,6 +22,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
originalPolicy.ExposedHeaders.Add("ExistingExposed");
|
||||
originalPolicy.SupportsCredentials = true;
|
||||
originalPolicy.PreflightMaxAge = TimeSpan.FromSeconds(12);
|
||||
originalPolicy.IsOriginAllowed = isOriginAllowed;
|
||||
|
||||
// Act
|
||||
var builder = new CorsPolicyBuilder(originalPolicy);
|
||||
|
|
@ -41,6 +43,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
Assert.NotSame(originalPolicy.ExposedHeaders, corsPolicy.ExposedHeaders);
|
||||
Assert.Equal(originalPolicy.ExposedHeaders, corsPolicy.ExposedHeaders);
|
||||
Assert.Equal(TimeSpan.FromSeconds(12), corsPolicy.PreflightMaxAge);
|
||||
Assert.Same(originalPolicy.IsOriginAllowed, corsPolicy.IsOriginAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -140,6 +143,35 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
Assert.Equal(new List<string>() { "*" }, corsPolicy.Origins);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetIsOriginAllowed_AddsIsOriginAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new CorsPolicyBuilder();
|
||||
Func<string, bool> isOriginAllowed = origin => true;
|
||||
|
||||
// Act
|
||||
builder.SetIsOriginAllowed(isOriginAllowed);
|
||||
|
||||
// Assert
|
||||
var corsPolicy = builder.Build();
|
||||
Assert.Same(corsPolicy.IsOriginAllowed, isOriginAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetIsOriginAllowedToAllowWildcardSubdomains_AllowsWildcardSubdomains()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new CorsPolicyBuilder("http://*.example.com");
|
||||
|
||||
// Act
|
||||
builder.SetIsOriginAllowedToAllowWildcardSubdomains();
|
||||
|
||||
// Assert
|
||||
var corsPolicy = builder.Build();
|
||||
Assert.True(corsPolicy.IsOriginAllowed("http://test.example.com"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WithMethods_AddsMethods()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||
{
|
||||
public sealed class CorsPolicyExtensionsTest
|
||||
{
|
||||
[Fact]
|
||||
public void IsOriginAnAllowedSubdomain_ReturnsTrueIfPolicyContainsOrigin()
|
||||
{
|
||||
// Arrange
|
||||
const string origin = "http://sub.domain";
|
||||
var policy = new CorsPolicy();
|
||||
policy.Origins.Add(origin);
|
||||
|
||||
// Act
|
||||
var actual = policy.IsOriginAnAllowedSubdomain(origin);
|
||||
|
||||
// Assert
|
||||
Assert.True(actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("http://sub.domain", "http://*.domain")]
|
||||
[InlineData("http://sub.sub.domain", "http://*.domain")]
|
||||
[InlineData("http://sub.sub.domain", "http://*.sub.domain")]
|
||||
[InlineData("http://sub.domain:4567", "http://*.domain:4567")]
|
||||
public void IsOriginAnAllowedSubdomain_ReturnsTrue_WhenASubdomain(string origin, string allowedOrigin)
|
||||
{
|
||||
// Arrange
|
||||
var policy = new CorsPolicy();
|
||||
policy.Origins.Add(allowedOrigin);
|
||||
|
||||
// Act
|
||||
var isAllowed = policy.IsOriginAnAllowedSubdomain(origin);
|
||||
|
||||
// Assert
|
||||
Assert.True(isAllowed);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("http://domain", "http://*.domain")]
|
||||
[InlineData("http://sub.domain", "http://domain")]
|
||||
[InlineData("http://sub.domain:1234", "http://*.domain:5678")]
|
||||
[InlineData("http://sub.domain", "http://domain.*")]
|
||||
[InlineData("http://sub.sub.domain", "http://sub.*.domain")]
|
||||
[InlineData("http://sub.domain.hacker", "http://*.domain")]
|
||||
[InlineData("https://sub.domain", "http://*.domain")]
|
||||
public void IsOriginAnAllowedSubdomain_ReturnsFalse_WhenNotASubdomain(string origin, string allowedOrigin)
|
||||
{
|
||||
// Arrange
|
||||
var policy = new CorsPolicy();
|
||||
policy.Origins.Add(allowedOrigin);
|
||||
|
||||
// Act
|
||||
var isAllowed = policy.IsOriginAnAllowedSubdomain(origin);
|
||||
|
||||
// Assert
|
||||
Assert.False(isAllowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
Assert.Empty(corsPolicy.Methods);
|
||||
Assert.Empty(corsPolicy.Origins);
|
||||
Assert.Null(corsPolicy.PreflightMaxAge);
|
||||
Assert.NotNull(corsPolicy.IsOriginAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -58,6 +58,26 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
Assert.False(result.VaryByOrigin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EvaluatePolicy_IsOriginAllowedReturnsFalse_ReturnsInvalidResult()
|
||||
{
|
||||
// Arrange
|
||||
var corsService = new CorsService(new TestCorsOptions());
|
||||
var requestContext = GetHttpContext(origin: "http://example.com");
|
||||
var policy = new CorsPolicy()
|
||||
{
|
||||
IsOriginAllowed = origin => false
|
||||
};
|
||||
policy.Origins.Add("example.com");
|
||||
|
||||
// Act
|
||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||
|
||||
// Assert
|
||||
Assert.Null(result.AllowedOrigin);
|
||||
Assert.False(result.VaryByOrigin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportCredentials_EmitsWildcardForOrigin()
|
||||
{
|
||||
|
|
@ -407,6 +427,28 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
Assert.Equal("http://example.com", result.AllowedOrigin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EvaluatePolicy_PreflightRequest_IsOriginAllowedReturnsTrue_ReturnsOrigin()
|
||||
{
|
||||
// Arrange
|
||||
var corsService = new CorsService(new TestCorsOptions());
|
||||
var requestContext = GetHttpContext(
|
||||
method: "OPTIONS",
|
||||
origin: "http://example.com",
|
||||
accessControlRequestMethod: "PUT");
|
||||
var policy = new CorsPolicy
|
||||
{
|
||||
IsOriginAllowed = origin => true
|
||||
};
|
||||
policy.Methods.Add("*");
|
||||
|
||||
// Act
|
||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("http://example.com", result.AllowedOrigin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EvaluatePolicy_PreflightRequest_SupportsCredentials_AllowCredentialsReturnsTrue()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||
{
|
||||
public sealed class UriHelpersTests
|
||||
{
|
||||
[Theory]
|
||||
[MemberData(nameof(IsSubdomainOfTestData))]
|
||||
public void TestIsSubdomainOf(Uri subdomain, Uri domain)
|
||||
{
|
||||
// Act
|
||||
bool isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain);
|
||||
|
||||
// Assert
|
||||
Assert.True(isSubdomain);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(IsNotSubdomainOfTestData))]
|
||||
public void TestIsSubdomainOf_ReturnsFalse_WhenNotSubdomain(Uri subdomain, Uri domain)
|
||||
{
|
||||
// Act
|
||||
bool isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain);
|
||||
|
||||
// Assert
|
||||
Assert.False(isSubdomain);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> IsSubdomainOfTestData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new object[] {new Uri("http://sub.domain"), new Uri("http://domain")},
|
||||
new object[] {new Uri("https://sub.domain"), new Uri("https://domain")},
|
||||
new object[] {new Uri("https://sub.domain:5678"), new Uri("https://domain:5678")},
|
||||
new object[] {new Uri("http://sub.sub.domain"), new Uri("http://domain")},
|
||||
new object[] {new Uri("http://sub.sub.domain"), new Uri("http://sub.domain")}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> IsNotSubdomainOfTestData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new object[] {new Uri("http://subdomain"), new Uri("http://domain")},
|
||||
new object[] {new Uri("https://sub.domain"), new Uri("http://domain")},
|
||||
new object[] {new Uri("https://sub.domain:1234"), new Uri("https://domain:5678")},
|
||||
new object[] {new Uri("http://domain.tld"), new Uri("http://domain")},
|
||||
new object[] {new Uri("http://sub.domain.tld"), new Uri("http://domain")},
|
||||
new object[] {new Uri("/relativeUri", UriKind.Relative), new Uri("http://domain")},
|
||||
new object[] {new Uri("http://sub.domain"), new Uri("/relative", UriKind.Relative)}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
{
|
||||
"version": "1.1.0-*",
|
||||
"buildOptions": {
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"dependencies": {
|
||||
"CorsMiddlewareWebSite": "1.0.0-*",
|
||||
"dotnet-test-xunit": "2.2.0-*",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true
|
||||
"emitEntryPoint": true,
|
||||
"keyFile": "../../../tools/Key.snk"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Cors": "1.2.0-*",
|
||||
|
|
|
|||
Loading…
Reference in New Issue