PR comments incorporated. Working on making SampleDestination dynamic- define the policy within the sample through a UI.
This commit is contained in:
parent
5dcf47ef12
commit
b3bdba1559
4
CORS.sln
4
CORS.sln
|
|
@ -21,9 +21,9 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "CorsMiddlewareWebSite", "te
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{960E0703-A8A5-44DF-AA87-B7C614683B3C}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleDestination", "SampleDestination\SampleDestination.xproj", "{F6675DC1-AA21-453B-89B6-DA425FB9C3A5}"
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleDestination", "samples\SampleDestination\SampleDestination.xproj", "{F6675DC1-AA21-453B-89B6-DA425FB9C3A5}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleOrigin", "SampleOrigin\SampleOrigin.xproj", "{99460370-AE5D-4DC9-8DBF-04DF66D6B21D}"
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleOrigin", "samples\SampleOrigin\SampleOrigin.xproj", "{99460370-AE5D-4DC9-8DBF-04DF66D6B21D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
|
|||
|
|
@ -19,9 +19,15 @@ Save the file and close it. Then clear your browser history.
|
|||
Run the sample
|
||||
*In a command prompt window, open the directory where you cloned the repository, and open the SampleDestination directory. Run the command: dotnet run
|
||||
*Repeat the above step in the SampleOrigin directory.
|
||||
*Open a browser window and go to http://origin.example.com
|
||||
*Open a browser window and go to http://origin.example.com:5001
|
||||
*Click the button to see CORS in action.
|
||||
|
||||
The SampleOrigin application will use port 5001, and SampleDestination will use 5000. Please ensure there are no other processes using those ports before running the CORS sample.
|
||||
|
||||
As an example, apart from GET, HEAD and POST requests, PUT requests are allowed in the CORS policy on SampleDestination. Any others, like DELETE, OPTIONS etc. are not allowed and throw an error.
|
||||
Content-Length has been added as an allowed header to the sample. Any other headers are not allowed and throw an error.
|
||||
To edit the policy, please see app.UseCors() method in the Startup.cs file of SampleDestination.
|
||||
|
||||
If using Visual Studio to launch the request origin:
|
||||
Open Visual Studio and in the launchSettings.json file for the SampleOrigin project, change the launchUrl under SampleOrigin to
|
||||
http://origin.example.com:8080. Using the dropdown near the Start button, choose SampleOrigin before pressing Start to ensure that it uses Kestrel
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ namespace SampleDestination
|
|||
.UseKestrel()
|
||||
.UseUrls("http://*:5000")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -19,10 +20,21 @@ namespace SampleDestination
|
|||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||
{
|
||||
loggerFactory.AddConsole();
|
||||
app.UseCors(policy => policy.WithOrigins("http://origin.example.com:8080"));
|
||||
|
||||
app.UseCors(policy => policy
|
||||
.WithOrigins("http://origin.example.com:5001")
|
||||
.WithMethods("PUT")
|
||||
.WithHeaders("Content-Length"));
|
||||
|
||||
app.Run(async context =>
|
||||
{
|
||||
await context.Response.WriteAsync("Status code of your request: " + context.Response.StatusCode.ToString());
|
||||
var responseHeaders = context.Response.Headers;
|
||||
foreach (var responseHeader in responseHeaders)
|
||||
{
|
||||
await context.Response.WriteAsync("\n"+responseHeader.Key+": "+responseHeader.Value);
|
||||
}
|
||||
|
||||
await context.Response.WriteAsync("\nStatus code of your request: " + context.Response.StatusCode.ToString());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,11 @@
|
|||
"version": "1.1.0-*",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.2.0-*",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.2.0-*",
|
||||
"Microsoft.Extensions.Logging.Console": "1.2.0-*",
|
||||
"Microsoft.AspNetCore.Cors": "1.2.0-*"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-*"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
|
|
@ -36,12 +31,7 @@
|
|||
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"wwwroot",
|
||||
"web.config"
|
||||
"wwwroot"
|
||||
]
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
|
|
@ -12,9 +12,8 @@ namespace SampleOrigin
|
|||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://*:8080")
|
||||
.UseUrls("http://*:5001")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,15 +4,10 @@
|
|||
"version": "1.1.0-*",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.2.0-*",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.2.0-*",
|
||||
"Microsoft.Extensions.Logging.Console": "1.2.0-*"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-*"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
|
|
@ -35,12 +30,7 @@
|
|||
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"wwwroot",
|
||||
"web.config"
|
||||
"wwwroot"
|
||||
]
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" stdoutLogEnabled="false" />
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
|
@ -2,30 +2,56 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<script type="text/javascript">
|
||||
|
||||
function createCORSRequest(method, url) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open(method, url, true);
|
||||
return request;
|
||||
<style>
|
||||
p {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
// Make the CORS request.
|
||||
function makeCORSRequest(method) {
|
||||
.button {
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
margin: 5px 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.green {
|
||||
background-color: #4CAF50;
|
||||
}
|
||||
|
||||
.red {
|
||||
background-color: indianred;
|
||||
}
|
||||
|
||||
.gray {
|
||||
background-color: gray;
|
||||
}
|
||||
</style>
|
||||
<title>CORS Sample</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
// Make the CORS request.
|
||||
function makeCORSRequest(method, headerName, headerValue) {
|
||||
// Destination server with CORS enabled.
|
||||
var url = 'http://destination.example.com:5000/api';
|
||||
var request = createCORSRequest(method , url);
|
||||
var url = 'http://destination.example.com:5000/';
|
||||
var request = new XMLHttpRequest();
|
||||
request.open(method, url, true);
|
||||
request.setRequestHeader(headerName, headerValue);
|
||||
|
||||
if (!request) {
|
||||
alert('CORS not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Response handlers.
|
||||
request.onload = function () {
|
||||
var text = request.responseText;
|
||||
alert('Response from CORS '+method+' request to ' + url + ': ' + text);
|
||||
alert('Response from CORS ' + method + ' request to ' + url + ': ' + text);
|
||||
};
|
||||
|
||||
request.onerror = function () {
|
||||
|
|
@ -34,16 +60,40 @@
|
|||
|
||||
request.send();
|
||||
}
|
||||
|
||||
</script>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<form method="post">
|
||||
<input id="clickMe" type="button" value="CORS Request" onclick="makeCORSRequest('GET');" />
|
||||
</form>
|
||||
<form method="post">
|
||||
<input id="clickMe" type="button" value="Invalid CORS Request" onclick="makeCORSRequest('DELETE');" />
|
||||
</form>
|
||||
<p>CORS Sample</p>
|
||||
Method: <input type="text" id="methodName" /><br /><br />
|
||||
Header Name: <input type="text" id="headerName" value="Content-Length" /> Header Value: <input type="text" id="headerValue" value="10" /><br /><br />
|
||||
<script>
|
||||
document.getElementById('methodName')
|
||||
.addEventListener("keyup", function (event) {
|
||||
event.preventDefault();
|
||||
if (event.keyCode == 13) {
|
||||
document.getElementById("headerName").focus();
|
||||
}
|
||||
});
|
||||
document.getElementById('headerName')
|
||||
.addEventListener("keyup", function (event) {
|
||||
event.preventDefault();
|
||||
if (event.keyCode == 13) {
|
||||
document.getElementById("headerValue").focus();
|
||||
}
|
||||
});
|
||||
document.getElementById('headerValue')
|
||||
.addEventListener("keyup", function (event) {
|
||||
event.preventDefault();
|
||||
if (event.keyCode == 13) {
|
||||
document.getElementById("CORS").click();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<button class="button gray" id="CORS" type="submit" onclick="makeCORSRequest(document.getElementById('methodName').value, document.getElementById('headerName').value, document.getElementById('headerValue').value);">Make a CORS Request</button><br /><br /><br /><br />
|
||||
|
||||
Method DELETE is not allowed:<button class="button red" id="InvalidMethodCORS" type="submit" onclick="makeCORSRequest('DELETE', 'Content-Length', '10');">Invalid Method CORS Request</button>
|
||||
Method PUT is allowed:<button class="button green" id="InvalidMethodCORS" type="submit" onclick="makeCORSRequest('PUT', 'Content-Length', '10');">Valid Method CORS Request</button><br /><br />
|
||||
|
||||
Header 'Max-Forwards' not supported:<button class="button red" id="InvalidHeaderCORS" type="submit" onclick="makeCORSRequest('PUT', 'Max-Forwards', 'x');">Invalid Header CORS Request</button>
|
||||
Header 'Content-Length' is supported:<button class="button green" id="InvalidHeaderCORS" type="submit" onclick="makeCORSRequest('PUT', 'Content-Length', 'x');">Valid Header CORS Request</button><br /><br />
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
/// </summary>
|
||||
/// <param name="options">The option model representing <see cref="CorsOptions"/>.</param>
|
||||
public CorsService(IOptions<CorsOptions> options)
|
||||
:this(options, loggerFactory: null)
|
||||
: this(options, loggerFactory: null)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -103,14 +103,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
return;
|
||||
}
|
||||
|
||||
_logger?.RequestHasOriginHeader(origin);
|
||||
if (!policy.AllowAnyOrigin && !policy.Origins.Contains(origin))
|
||||
{
|
||||
_logger?.RequestHasOriginHeader();
|
||||
_logger?.PolicyFailure($"Request origin {origin} does not have permission to access the resource.");
|
||||
_logger?.PolicyFailure();
|
||||
_logger?.OriginNotAllowed(origin);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger?.RequestHasOriginHeader();
|
||||
AddOriginToResult(origin, policy, result);
|
||||
result.SupportsCredentials = policy.SupportsCredentials;
|
||||
AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders);
|
||||
|
|
@ -126,14 +126,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
return;
|
||||
}
|
||||
|
||||
_logger?.RequestHasOriginHeader(origin);
|
||||
if (!policy.AllowAnyOrigin && !policy.Origins.Contains(origin))
|
||||
{
|
||||
_logger?.RequestHasOriginHeader();
|
||||
_logger?.PolicyFailure($"Request origin {origin} does not have permission to access the resource.");
|
||||
_logger?.PolicyFailure();
|
||||
_logger?.OriginNotAllowed(origin);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger?.RequestHasOriginHeader();
|
||||
var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod];
|
||||
if (StringValues.IsNullOrEmpty(accessControlRequestMethod))
|
||||
{
|
||||
|
|
@ -158,18 +158,25 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
|
||||
if (!found)
|
||||
{
|
||||
_logger?.PolicyFailure($"Request method {accessControlRequestMethod} not allowed in CORS policy.");
|
||||
return;
|
||||
_logger?.PolicyFailure();
|
||||
_logger?.AccessControlMethodNotAllowed(accessControlRequestMethod);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!policy.AllowAnyHeader &&
|
||||
requestHeaders != null &&
|
||||
!requestHeaders.All(header => CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase) ||
|
||||
policy.Headers.Contains(header, StringComparer.OrdinalIgnoreCase)))
|
||||
requestHeaders != null)
|
||||
{
|
||||
_logger?.PolicyFailure($"One or more request header(s) not allowed in CORS policy.");
|
||||
return;
|
||||
foreach (var requestHeader in requestHeaders)
|
||||
{
|
||||
if (!CorsConstants.SimpleRequestHeaders.Contains(requestHeader, StringComparer.OrdinalIgnoreCase) &&
|
||||
!policy.Headers.Contains(requestHeader, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
_logger?.PolicyFailure();
|
||||
_logger?.RequestHeaderNotAllowed(requestHeader);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddOriginToResult(origin, policy, result);
|
||||
|
|
|
|||
|
|
@ -9,22 +9,25 @@ namespace Microsoft.AspNetCore.Cors.Internal
|
|||
internal static class CORSLoggerExtensions
|
||||
{
|
||||
private static readonly Action<ILogger, Exception> _isPreflightRequest;
|
||||
private static readonly Action<ILogger, Exception> _requestHasOriginHeader;
|
||||
private static readonly Action<ILogger, string, Exception> _requestHasOriginHeader;
|
||||
private static readonly Action<ILogger, Exception> _requestDoesNotHaveOriginHeader;
|
||||
private static readonly Action<ILogger, Exception> _policySuccess;
|
||||
private static readonly Action<ILogger, string, Exception> _policyFailure;
|
||||
private static readonly Action<ILogger, Exception> _policyFailure;
|
||||
private static readonly Action<ILogger, string, Exception> _originNotAllowed;
|
||||
private static readonly Action<ILogger, string, Exception> _accessControlMethodNotAllowed;
|
||||
private static readonly Action<ILogger, string, Exception> _requestHeaderNotAllowed;
|
||||
|
||||
static CORSLoggerExtensions()
|
||||
{
|
||||
_isPreflightRequest = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
1,
|
||||
"This is a preflight request.");
|
||||
"The request is a preflight request.");
|
||||
|
||||
_requestHasOriginHeader = LoggerMessage.Define(
|
||||
_requestHasOriginHeader = LoggerMessage.Define<string>(
|
||||
LogLevel.Debug,
|
||||
2,
|
||||
"The request has an origin header.");
|
||||
"The request has an origin header: '{origin}'.");
|
||||
|
||||
_requestDoesNotHaveOriginHeader = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
|
|
@ -36,10 +39,25 @@ namespace Microsoft.AspNetCore.Cors.Internal
|
|||
4,
|
||||
"Policy execution successful.");
|
||||
|
||||
_policyFailure = LoggerMessage.Define<string>(
|
||||
_policyFailure = LoggerMessage.Define(
|
||||
LogLevel.Information,
|
||||
5,
|
||||
"Policy execution failed. {FailureReason}");
|
||||
"Policy execution failed.");
|
||||
|
||||
_originNotAllowed = LoggerMessage.Define<string>(
|
||||
LogLevel.Information,
|
||||
6,
|
||||
"Request origin {origin} does not have permission to access the resource.");
|
||||
|
||||
_accessControlMethodNotAllowed = LoggerMessage.Define<string>(
|
||||
LogLevel.Information,
|
||||
7,
|
||||
"Request method {accessControlRequestMethod} not allowed in CORS policy.");
|
||||
|
||||
_requestHeaderNotAllowed = LoggerMessage.Define<string>(
|
||||
LogLevel.Information,
|
||||
8,
|
||||
"Request header '{requestHeader}' not allowed in CORS policy.");
|
||||
}
|
||||
|
||||
public static void IsPreflightRequest(this ILogger logger)
|
||||
|
|
@ -47,9 +65,9 @@ namespace Microsoft.AspNetCore.Cors.Internal
|
|||
_isPreflightRequest(logger, null);
|
||||
}
|
||||
|
||||
public static void RequestHasOriginHeader(this ILogger logger)
|
||||
public static void RequestHasOriginHeader(this ILogger logger, string origin)
|
||||
{
|
||||
_requestHasOriginHeader(logger, null);
|
||||
_requestHasOriginHeader(logger, origin, null);
|
||||
}
|
||||
|
||||
public static void RequestDoesNotHaveOriginHeader(this ILogger logger)
|
||||
|
|
@ -62,9 +80,24 @@ namespace Microsoft.AspNetCore.Cors.Internal
|
|||
_policySuccess(logger, null);
|
||||
}
|
||||
|
||||
public static void PolicyFailure(this ILogger logger, string failureReason)
|
||||
public static void PolicyFailure(this ILogger logger)
|
||||
{
|
||||
_policyFailure(logger, failureReason, null);
|
||||
_policyFailure(logger, null);
|
||||
}
|
||||
|
||||
public static void OriginNotAllowed(this ILogger logger, string origin)
|
||||
{
|
||||
_originNotAllowed(logger, origin, null);
|
||||
}
|
||||
|
||||
public static void AccessControlMethodNotAllowed(this ILogger logger, string accessControlMethod)
|
||||
{
|
||||
_accessControlMethodNotAllowed(logger, accessControlMethod, null);
|
||||
}
|
||||
|
||||
public static void RequestHeaderNotAllowed(this ILogger logger, string requestHeader)
|
||||
{
|
||||
_requestHeaderNotAllowed(logger, requestHeader, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,39 +228,41 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
Assert.Contains("PUT", result.AllowedMethods);
|
||||
}
|
||||
|
||||
public static TheoryData<string, string, string[], string, string> PreflightRequests_LoggingData
|
||||
public static TheoryData<LogData> PreflightRequests_LoggingData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<string, string, string[], string, string>
|
||||
return new TheoryData<LogData>
|
||||
{
|
||||
{
|
||||
"http://example.com",
|
||||
"PUT",
|
||||
null,
|
||||
"The request has an origin header.",
|
||||
"Policy execution failed. Request origin http://example.com does not have permission to access the resource."
|
||||
new LogData {
|
||||
origin = "http://example.com",
|
||||
method = "PUT",
|
||||
headers = null,
|
||||
originLogMessage = "The request has an origin header: 'http://example.com'.",
|
||||
policyLogMessage = "Policy execution failed.",
|
||||
failureReason = "Request origin http://example.com does not have permission to access the resource."
|
||||
}
|
||||
},
|
||||
{
|
||||
"http://allowed.example.com",
|
||||
"DELETE",
|
||||
null,
|
||||
"The request has an origin header.",
|
||||
"Policy execution failed. Request method DELETE not allowed in CORS policy."
|
||||
new LogData {
|
||||
origin = "http://allowed.example.com",
|
||||
method = "DELETE",
|
||||
headers = null,
|
||||
originLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
|
||||
policyLogMessage = "Policy execution failed.",
|
||||
failureReason = "Request method DELETE not allowed in CORS policy."
|
||||
}
|
||||
},
|
||||
{
|
||||
"http://allowed.example.com",
|
||||
"PUT",
|
||||
new[] { "test" },
|
||||
"The request has an origin header.",
|
||||
"Policy execution failed. One or more request header(s) not allowed in CORS policy."
|
||||
},
|
||||
{
|
||||
"http://allowed.example.com",
|
||||
"PUT",
|
||||
null,
|
||||
"The request has an origin header.",
|
||||
"Policy execution successful."
|
||||
new LogData {
|
||||
origin = "http://allowed.example.com",
|
||||
method = "PUT",
|
||||
headers = new[] { "test" },
|
||||
originLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
|
||||
policyLogMessage = "Policy execution failed.",
|
||||
failureReason = "Request header 'test' not allowed in CORS policy."
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -268,13 +270,13 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(PreflightRequests_LoggingData))]
|
||||
public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader(string origin, string method, string[] headers, string originLogMessage, string policyLogMessage)
|
||||
public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicyFailed(LogData logData)
|
||||
{
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
|
||||
var requestContext = GetHttpContext(method: "OPTIONS", origin: origin, accessControlRequestMethod: method, accessControlRequestHeaders: headers);
|
||||
var requestContext = GetHttpContext(method: "OPTIONS", origin: logData.origin, accessControlRequestMethod: logData.method, accessControlRequestHeaders: logData.headers);
|
||||
var policy = new CorsPolicy();
|
||||
policy.Origins.Add("http://allowed.example.com");
|
||||
policy.Methods.Add("PUT");
|
||||
|
|
@ -282,9 +284,30 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
// Act
|
||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||
|
||||
Assert.Equal("This is a preflight request.", sink.Writes[0].State.ToString());
|
||||
Assert.Equal(originLogMessage, sink.Writes[1].State.ToString());
|
||||
Assert.Equal(policyLogMessage, sink.Writes[2].State.ToString());
|
||||
Assert.Equal("The request is a preflight request.", sink.Writes[0].State.ToString());
|
||||
Assert.Equal(logData.originLogMessage, sink.Writes[1].State.ToString());
|
||||
Assert.Equal(logData.policyLogMessage, sink.Writes[2].State.ToString());
|
||||
Assert.Equal(logData.failureReason, sink.Writes[3].State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicySucceeded()
|
||||
{
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
|
||||
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://allowed.example.com", accessControlRequestMethod: "PUT");
|
||||
var policy = new CorsPolicy();
|
||||
policy.Origins.Add("http://allowed.example.com");
|
||||
policy.Methods.Add("PUT");
|
||||
|
||||
// Act
|
||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||
|
||||
Assert.Equal("The request is a preflight request.", sink.Writes[0].State.ToString());
|
||||
Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", sink.Writes[1].State.ToString());
|
||||
Assert.Equal("Policy execution successful.", sink.Writes[2].State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -302,47 +325,45 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
// Act
|
||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||
|
||||
Assert.Equal("This is a preflight request.", sink.Writes[0].State.ToString());
|
||||
Assert.Equal("The request is a preflight request.", sink.Writes[0].State.ToString());
|
||||
Assert.Equal("The request does not have an origin header.", sink.Writes[1].State.ToString());
|
||||
}
|
||||
|
||||
public static TheoryData<string, string, string> NonPreflightRequests_LoggingData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<string, string, string>
|
||||
{
|
||||
{
|
||||
"http://example.com",
|
||||
"The request has an origin header.",
|
||||
"Policy execution failed. Request origin http://example.com does not have permission to access the resource."
|
||||
},
|
||||
{
|
||||
"http://allowed.example.com",
|
||||
"The request has an origin header.",
|
||||
"Policy execution successful."
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(NonPreflightRequests_LoggingData))]
|
||||
public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader(string origin, string originlogMessage, string policyLogMessage)
|
||||
[Fact]
|
||||
public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicyFailed()
|
||||
{
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
|
||||
var requestContext = GetHttpContext(origin: origin);
|
||||
var requestContext = GetHttpContext(origin: "http://example.com");
|
||||
var policy = new CorsPolicy();
|
||||
policy.Origins.Add("http://allowed.example.com");
|
||||
|
||||
// Act
|
||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||
|
||||
Assert.Equal(originlogMessage, sink.Writes[0].State.ToString());
|
||||
Assert.Equal(policyLogMessage, sink.Writes[1].State.ToString());
|
||||
Assert.Equal("The request has an origin header: 'http://example.com'.", sink.Writes[0].State.ToString());
|
||||
Assert.Equal("Policy execution failed.", sink.Writes[1].State.ToString());
|
||||
Assert.Equal("Request origin http://example.com does not have permission to access the resource.", sink.Writes[2].State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicySucceeded()
|
||||
{
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
|
||||
var requestContext = GetHttpContext(origin: "http://allowed.example.com");
|
||||
var policy = new CorsPolicy();
|
||||
policy.Origins.Add("http://allowed.example.com");
|
||||
|
||||
// Act
|
||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||
|
||||
Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", sink.Writes[0].State.ToString());
|
||||
Assert.Equal("Policy execution successful.", sink.Writes[1].State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1049,5 +1070,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
|||
|
||||
return context;
|
||||
}
|
||||
|
||||
public struct LogData
|
||||
{
|
||||
public string origin { get; set; }
|
||||
public string method { get; set; }
|
||||
public string[] headers { get; set; }
|
||||
public string originLogMessage { get; set; }
|
||||
public string policyLogMessage { get; set; }
|
||||
public string failureReason { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue