Asp.net core 配置cors以允许使用ASP.NET核心(ASP.NET 5、MVC6、VNext)的所有子域

Asp.net core 配置cors以允许使用ASP.NET核心(ASP.NET 5、MVC6、VNext)的所有子域,asp.net-core,cors,asp.net-core-mvc,Asp.net Core,Cors,Asp.net Core Mvc,我在ASP.NET核心web应用程序中正确设置了cors。我正在使用以下软件包 "Microsoft.AspNet.Cors": "6.0.0-rc1-final" 下面是startup.cs代码段 public virtual IServiceProvider ConfigureServices(IServiceCollection services) { services.AddCors ( options => {

我在ASP.NET核心web应用程序中正确设置了cors。我正在使用以下软件包

"Microsoft.AspNet.Cors": "6.0.0-rc1-final"
下面是startup.cs代码段

public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddCors
    (
        options =>
        {
            options.AddPolicy
            (
                CORSDefaults.PolicyName, 
                builder =>
                {
                    //From config...
                    var allowedDomains = new []{"http://aaa.somewhere.com","https://aaa.somewhere.com","http://bbb.somewhere.com","https://bbb.somewhere.com"};

                    //Load it
                    builder
                        .WithOrigins(allowedDomains)
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                }
            );
        }
    );
}
这非常有效,只是要允许的子域列表正在快速增长,我想允许“某处.com”的所有子域。类似“*.somewhere.com”的东西。我似乎找不到任何关于如何在新的ASP.NET核心(MVC6、ASP.NET5、VNext)中实现这一点的文档。我找到的所有演示如何实现这一点的文档/示例都是针对MVC或WebApi的早期版本的。如何在新堆栈中实现这一点?

开箱即用的方法使用
policy.Origins.Contains(origin)
评估请求。因此,似乎没有一种简单的方法来完成您需要的操作,因为
列表必须包含源代码。您可以实现自己的,继承现成的
CorsService
已经提供的内容,并调整方法来处理
*.mydomain.com
通配符

Edit以下是我使用
yo aspnet
生成
1.0.0-rc1-update2
Web Api项目所完成的工作。它起作用了。在Startup.cs中注册您的服务(有关详细信息,请参阅。)

我向ASP.NET团队介绍了这一更改,希望它能进入nuget包。在那之前,我使用这个变通方法

下面,您将像往常一样注册cors,但必须在di容器中注册WildCardCorsService类

public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.TryAdd(ServiceDescriptor.Transient<ICorsService, WildCardCorsService>());
    services.AddCors
    (
        options =>
        {
            options.AddPolicy
            (
                CORSDefaults.PolicyName, 
                builder =>
                {
                    builder
                        .WithOrigins("http://*.withwildcardsubdomain.com", "http://nowildcard.com")
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                }
            );
        }
    );
}
公共虚拟iSeries Provider配置服务(iSeries收集服务)
{
services.TryAdd(servicescriptor.Transient());
服务.AddCors
(
选项=>
{
options.AddPolicy
(
CORSDefaults.PolicyName,
生成器=>
{
建设者
.WithOrigins(“http://*.withwildcardsubdomain.com”http://nowildcard.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
}
);
}
);
}
在解决方案中本地保存此类。它是Microsoft.AspNet.Cors.CorsService.cs类的复制和编辑,允许它处理通配符子域。如果找到通配符字符“*”,它将检查根域是否与允许的源和实际源匹配。它不支持部分通配符匹配

namespace Microsoft.AspNet.Cors.Infrastructure
{
    /// <summary>
    /// This ICorsService should be used in place of the official default CorsService to support origins 
    /// like http://*.example.comwhich will allow any subdomain for example.com
    /// </summary>
    public class WildCardCorsService : ICorsService
    {
        private readonly CorsOptions _options;

        /// <summary>
        /// Creates a new instance of the <see cref="CorsService"/>.
        /// </summary>
        /// <param name="options">The option model representing <see cref="CorsOptions"/>.</param>
        public WildCardCorsService(IOptions<CorsOptions> options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _options = options.Value;
        }

        /// <summary>
        /// Looks up a policy using the <paramref name="policyName"/> and then evaluates the policy using the passed in
        /// <paramref name="context"/>.
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="policyName"></param>
        /// <returns>A <see cref="CorsResult"/> which contains the result of policy evaluation and can be
        /// used by the caller to set appropriate response headers.</returns>
        public CorsResult EvaluatePolicy(HttpContext context, string policyName)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var policy = _options.GetPolicy(policyName);
            return EvaluatePolicy(context, policy);
        }

        /// <inheritdoc />
        public CorsResult EvaluatePolicy(HttpContext context, CorsPolicy policy)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (policy == null)
            {
                throw new ArgumentNullException(nameof(policy));
            }

            var corsResult = new CorsResult();
            var accessControlRequestMethod = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlRequestMethod];
            if (string.Equals(context.Request.Method, Microsoft.AspNet.Cors.Infrastructure.CorsConstants.PreflightHttpMethod, StringComparison.Ordinal) &&
                !StringValues.IsNullOrEmpty(accessControlRequestMethod))
            {
                EvaluatePreflightRequest(context, policy, corsResult);
            }
            else
            {
                EvaluateRequest(context, policy, corsResult);
            }

            return corsResult;
        }

        public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.Origin];
            if (!OriginIsAllowed(origin, policy))
            {
                return;
            }

            AddOriginToResult(origin, policy, result);
            result.SupportsCredentials = policy.SupportsCredentials;
            AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders);
        }

        public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.Origin];
            if (!OriginIsAllowed(origin, policy))
            {
                return;
            }

            var accessControlRequestMethod = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlRequestMethod];
            if (StringValues.IsNullOrEmpty(accessControlRequestMethod))
            {
                return;
            }

            var requestHeaders =
                context.Request.Headers.GetCommaSeparatedValues(Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlRequestHeaders);

            if (!policy.AllowAnyMethod && !policy.Methods.Contains(accessControlRequestMethod))
            {
                return;
            }

            if (!policy.AllowAnyHeader &&
                requestHeaders != null &&
                !requestHeaders.All(header => Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase) ||
                                              policy.Headers.Contains(header, StringComparer.OrdinalIgnoreCase)))
            {
                return;
            }

            AddOriginToResult(origin, policy, result);
            result.SupportsCredentials = policy.SupportsCredentials;
            result.PreflightMaxAge = policy.PreflightMaxAge;
            result.AllowedMethods.Add(accessControlRequestMethod);
            AddHeaderValues(result.AllowedHeaders, requestHeaders);
        }

        /// <inheritdoc />
        public virtual void ApplyResult(CorsResult result, HttpResponse response)
        {
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            var headers = response.Headers;

            if (result.AllowedOrigin != null)
            {
                headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowOrigin] = result.AllowedOrigin;
            }

            if (result.VaryByOrigin)
            {
                headers["Vary"] = "Origin";
            }

            if (result.SupportsCredentials)
            {
                headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowCredentials] = "true";
            }

            if (result.AllowedMethods.Count > 0)
            {
                // Filter out simple methods
                var nonSimpleAllowMethods = result.AllowedMethods
                    .Where(m =>
                        !Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleMethods.Contains(m, StringComparer.OrdinalIgnoreCase))
                    .ToArray();

                if (nonSimpleAllowMethods.Length > 0)
                {
                    headers.SetCommaSeparatedValues(
                        Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowMethods,
                        nonSimpleAllowMethods);
                }
            }

            if (result.AllowedHeaders.Count > 0)
            {
                // Filter out simple request headers
                var nonSimpleAllowRequestHeaders = result.AllowedHeaders
                    .Where(header =>
                        !Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase))
                    .ToArray();

                if (nonSimpleAllowRequestHeaders.Length > 0)
                {
                    headers.SetCommaSeparatedValues(
                        Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowHeaders,
                        nonSimpleAllowRequestHeaders);
                }
            }

            if (result.AllowedExposedHeaders.Count > 0)
            {
                // Filter out simple response headers
                var nonSimpleAllowResponseHeaders = result.AllowedExposedHeaders
                    .Where(header =>
                        !Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleResponseHeaders.Contains(header, StringComparer.OrdinalIgnoreCase))
                    .ToArray();

                if (nonSimpleAllowResponseHeaders.Length > 0)
                {
                    headers.SetCommaSeparatedValues(
                        Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlExposeHeaders,
                        nonSimpleAllowResponseHeaders);
                }
            }

            if (result.PreflightMaxAge.HasValue)
            {
                headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlMaxAge]
                    = result.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture);
            }
        }

        protected virtual bool OriginIsAllowed(string origin, CorsPolicy policy)
        {
            if (!string.IsNullOrWhiteSpace(origin) &&
                (policy.AllowAnyOrigin ||
                 policy.Origins.Contains(origin) ||
                 IsWildCardSubdomainMatch(origin, policy)))
                return true;

            return false;
        }

        private void AddOriginToResult(string origin, CorsPolicy policy, CorsResult result)
        {
            if (policy.AllowAnyOrigin)
            {
                if (policy.SupportsCredentials)
                {
                    result.AllowedOrigin = origin;
                    result.VaryByOrigin = true;
                }
                else
                {
                    result.AllowedOrigin = Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AnyOrigin;
                }
            }
            else
            {
                result.AllowedOrigin = origin;
            }
        }

        private static void AddHeaderValues(IList<string> target, IEnumerable<string> headerValues)
        {
            if (headerValues == null)
            {
                return;
            }

            foreach (var current in headerValues)
            {
                target.Add(current);
            }
        }

        private bool IsWildCardSubdomainMatch(string origin, CorsPolicy policy)
        {
            var actualOriginUri = new Uri(origin);
            var actualOriginRootDomain = GetRootDomain(actualOriginUri);

            foreach (var o in policy.Origins)
            {
                if (!o.Contains("*"))
                    continue;

                // 1) CANNOT USE System.Text.RegularExpression since it does not exist in .net platform 5.4 (which the Microsoft.AspNet.Cors project.json targets)
                // 2) '*' char is not valid for creation of a URI object so we replace it just for this comparison
                var allowedOriginUri = new Uri(o.Replace("*", "SOMELETTERS"));
                if (allowedOriginUri.Scheme == actualOriginUri.Scheme &&
                    actualOriginRootDomain == GetRootDomain(allowedOriginUri))
                    return true;
            }

            return false;
        }

        private string GetRootDomain(Uri uri)
        {
            //Got this snippet here http://stackoverflow.com/questions/16473838/get-domain-name-of-a-url-in-c-sharp-net
            var host = uri.Host;
            int index = host.LastIndexOf('.'), last = 3;

            while (index > 0 && index >= last - 3)
            {
                last = index;
                index = host.LastIndexOf('.', last - 1);
            }

            return host.Substring(index + 1);
        }
    }

    /// <summary>
    /// Needed to copy these in since some of them are internal to the Microsoft.AspNet.Cors project
    /// </summary>
    public static class CorsConstants
    {
        /// <summary>The HTTP method for the CORS preflight request.</summary>
        public static readonly string PreflightHttpMethod = "OPTIONS";
        /// <summary>The Origin request header.</summary>
        public static readonly string Origin = "Origin";
        /// <summary>
        /// The value for the Access-Control-Allow-Origin response header to allow all origins.
        /// </summary>
        public static readonly string AnyOrigin = "*";
        /// <summary>The Access-Control-Request-Method request header.</summary>
        public static readonly string AccessControlRequestMethod = "Access-Control-Request-Method";
        /// <summary>The Access-Control-Request-Headers request header.</summary>
        public static readonly string AccessControlRequestHeaders = "Access-Control-Request-Headers";
        /// <summary>The Access-Control-Allow-Origin response header.</summary>
        public static readonly string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
        /// <summary>The Access-Control-Allow-Headers response header.</summary>
        public static readonly string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
        /// <summary>The Access-Control-Expose-Headers response header.</summary>
        public static readonly string AccessControlExposeHeaders = "Access-Control-Expose-Headers";
        /// <summary>The Access-Control-Allow-Methods response header.</summary>
        public static readonly string AccessControlAllowMethods = "Access-Control-Allow-Methods";
        /// <summary>The Access-Control-Allow-Credentials response header.</summary>
        public static readonly string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
        /// <summary>The Access-Control-Max-Age response header.</summary>
        public static readonly string AccessControlMaxAge = "Access-Control-Max-Age";
        internal static readonly string[] SimpleRequestHeaders = new string[4]
        {
      "Origin",
      "Accept",
      "Accept-Language",
      "Content-Language"
        };
        internal static readonly string[] SimpleResponseHeaders = new string[6]
        {
      "Cache-Control",
      "Content-Language",
      "Content-Type",
      "Expires",
      "Last-Modified",
      "Pragma"
        };
        internal static readonly string[] SimpleMethods = new string[3]
        {
      "GET",
      "HEAD",
      "POST"
        };
    }
}
名称空间Microsoft.AspNet.Cors.Infrastructure
{
/// 
///应使用此ICorsService代替官方默认的CorsService来支持源代码
///例如http://*.example.com,它将允许example.com的任何子域
/// 
公共类WildCardCorsService:ICorsService
{
私人只读公司选项;
/// 
///创建的新实例。
/// 
///期权模型代表了一种新的价值观。
公共通配符公司服务(IOPS选项)
{
如果(选项==null)
{
抛出新ArgumentNullException(nameof(options));
}
_选项=选项.值;
}
/// 
///使用查找策略,然后使用传入的评估策略
/// .
/// 
/// 
/// 
///包含策略评估结果的,可以
///调用方用于设置适当的响应头。
public CorsResult EvaluatePolicy(HttpContext上下文,字符串policyName)
{
if(上下文==null)
{
抛出新ArgumentNullException(nameof(context));
}
var policy=\u options.GetPolicy(policyName);
返回评估策略(上下文、策略);
}
/// 
公共公司结果评估策略(HttpContext上下文、公司策略)
{
if(上下文==null)
{
抛出新ArgumentNullException(nameof(context));
}
如果(策略==null)
{
抛出新的ArgumentNullException(nameof(policy));
}
var corsResult=新的corsResult();
var accessControlRequestMethod=context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.accessControlRequestMethod];
if(string.Equals(context.Request.Method、Microsoft.AspNet.Cors.Infrastructure.CorsConstants.preflighttpmethod、StringComparison.Ordinal)&&
!StringValues.IsNullOrEmpty(accessControlRequestMethod))
{
EvaluatePreflightRequest(上下文、策略、corsResult);
}
其他的
{
EvaluaterRequest(上下文、策略、corsResult);
}
返回结果;
}
公共虚拟void EvaluateRequest(HttpContext上下文、公司策略、公司结果)
{
var origin=context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.origin];
如果(!OriginIsAllowed(原产地、保单))
{
返回;
}
AddOriginToResult(来源、政策、结果);
result.SupportsCredentials=policy.SupportsCredentials;
AddHeaderValue(result.AllowedExposedHeaders、policy.ExposedHeaders);
}
公共虚拟无效EvaluatePreflightRequest(HttpContext上下文、CorsPolicy策略、CorsResult结果)
{
var origin=context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.origin];
如果(!OriginIsAllowed(原产地、保单))
{
返回;
}
var accessControlRequestMethod=context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.accessControlRequestMethod];
if(StringValues.IsNullOrEmpty(accessControlRequestMethod))
{
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.TryAdd(ServiceDescriptor.Transient<ICorsService, WildCardCorsService>());
    services.AddCors
    (
        options =>
        {
            options.AddPolicy
            (
                CORSDefaults.PolicyName, 
                builder =>
                {
                    builder
                        .WithOrigins("http://*.withwildcardsubdomain.com", "http://nowildcard.com")
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                }
            );
        }
    );
}
namespace Microsoft.AspNet.Cors.Infrastructure
{
    /// <summary>
    /// This ICorsService should be used in place of the official default CorsService to support origins 
    /// like http://*.example.comwhich will allow any subdomain for example.com
    /// </summary>
    public class WildCardCorsService : ICorsService
    {
        private readonly CorsOptions _options;

        /// <summary>
        /// Creates a new instance of the <see cref="CorsService"/>.
        /// </summary>
        /// <param name="options">The option model representing <see cref="CorsOptions"/>.</param>
        public WildCardCorsService(IOptions<CorsOptions> options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _options = options.Value;
        }

        /// <summary>
        /// Looks up a policy using the <paramref name="policyName"/> and then evaluates the policy using the passed in
        /// <paramref name="context"/>.
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="policyName"></param>
        /// <returns>A <see cref="CorsResult"/> which contains the result of policy evaluation and can be
        /// used by the caller to set appropriate response headers.</returns>
        public CorsResult EvaluatePolicy(HttpContext context, string policyName)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var policy = _options.GetPolicy(policyName);
            return EvaluatePolicy(context, policy);
        }

        /// <inheritdoc />
        public CorsResult EvaluatePolicy(HttpContext context, CorsPolicy policy)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (policy == null)
            {
                throw new ArgumentNullException(nameof(policy));
            }

            var corsResult = new CorsResult();
            var accessControlRequestMethod = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlRequestMethod];
            if (string.Equals(context.Request.Method, Microsoft.AspNet.Cors.Infrastructure.CorsConstants.PreflightHttpMethod, StringComparison.Ordinal) &&
                !StringValues.IsNullOrEmpty(accessControlRequestMethod))
            {
                EvaluatePreflightRequest(context, policy, corsResult);
            }
            else
            {
                EvaluateRequest(context, policy, corsResult);
            }

            return corsResult;
        }

        public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.Origin];
            if (!OriginIsAllowed(origin, policy))
            {
                return;
            }

            AddOriginToResult(origin, policy, result);
            result.SupportsCredentials = policy.SupportsCredentials;
            AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders);
        }

        public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result)
        {
            var origin = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.Origin];
            if (!OriginIsAllowed(origin, policy))
            {
                return;
            }

            var accessControlRequestMethod = context.Request.Headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlRequestMethod];
            if (StringValues.IsNullOrEmpty(accessControlRequestMethod))
            {
                return;
            }

            var requestHeaders =
                context.Request.Headers.GetCommaSeparatedValues(Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlRequestHeaders);

            if (!policy.AllowAnyMethod && !policy.Methods.Contains(accessControlRequestMethod))
            {
                return;
            }

            if (!policy.AllowAnyHeader &&
                requestHeaders != null &&
                !requestHeaders.All(header => Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase) ||
                                              policy.Headers.Contains(header, StringComparer.OrdinalIgnoreCase)))
            {
                return;
            }

            AddOriginToResult(origin, policy, result);
            result.SupportsCredentials = policy.SupportsCredentials;
            result.PreflightMaxAge = policy.PreflightMaxAge;
            result.AllowedMethods.Add(accessControlRequestMethod);
            AddHeaderValues(result.AllowedHeaders, requestHeaders);
        }

        /// <inheritdoc />
        public virtual void ApplyResult(CorsResult result, HttpResponse response)
        {
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            var headers = response.Headers;

            if (result.AllowedOrigin != null)
            {
                headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowOrigin] = result.AllowedOrigin;
            }

            if (result.VaryByOrigin)
            {
                headers["Vary"] = "Origin";
            }

            if (result.SupportsCredentials)
            {
                headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowCredentials] = "true";
            }

            if (result.AllowedMethods.Count > 0)
            {
                // Filter out simple methods
                var nonSimpleAllowMethods = result.AllowedMethods
                    .Where(m =>
                        !Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleMethods.Contains(m, StringComparer.OrdinalIgnoreCase))
                    .ToArray();

                if (nonSimpleAllowMethods.Length > 0)
                {
                    headers.SetCommaSeparatedValues(
                        Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowMethods,
                        nonSimpleAllowMethods);
                }
            }

            if (result.AllowedHeaders.Count > 0)
            {
                // Filter out simple request headers
                var nonSimpleAllowRequestHeaders = result.AllowedHeaders
                    .Where(header =>
                        !Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase))
                    .ToArray();

                if (nonSimpleAllowRequestHeaders.Length > 0)
                {
                    headers.SetCommaSeparatedValues(
                        Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlAllowHeaders,
                        nonSimpleAllowRequestHeaders);
                }
            }

            if (result.AllowedExposedHeaders.Count > 0)
            {
                // Filter out simple response headers
                var nonSimpleAllowResponseHeaders = result.AllowedExposedHeaders
                    .Where(header =>
                        !Microsoft.AspNet.Cors.Infrastructure.CorsConstants.SimpleResponseHeaders.Contains(header, StringComparer.OrdinalIgnoreCase))
                    .ToArray();

                if (nonSimpleAllowResponseHeaders.Length > 0)
                {
                    headers.SetCommaSeparatedValues(
                        Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlExposeHeaders,
                        nonSimpleAllowResponseHeaders);
                }
            }

            if (result.PreflightMaxAge.HasValue)
            {
                headers[Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AccessControlMaxAge]
                    = result.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture);
            }
        }

        protected virtual bool OriginIsAllowed(string origin, CorsPolicy policy)
        {
            if (!string.IsNullOrWhiteSpace(origin) &&
                (policy.AllowAnyOrigin ||
                 policy.Origins.Contains(origin) ||
                 IsWildCardSubdomainMatch(origin, policy)))
                return true;

            return false;
        }

        private void AddOriginToResult(string origin, CorsPolicy policy, CorsResult result)
        {
            if (policy.AllowAnyOrigin)
            {
                if (policy.SupportsCredentials)
                {
                    result.AllowedOrigin = origin;
                    result.VaryByOrigin = true;
                }
                else
                {
                    result.AllowedOrigin = Microsoft.AspNet.Cors.Infrastructure.CorsConstants.AnyOrigin;
                }
            }
            else
            {
                result.AllowedOrigin = origin;
            }
        }

        private static void AddHeaderValues(IList<string> target, IEnumerable<string> headerValues)
        {
            if (headerValues == null)
            {
                return;
            }

            foreach (var current in headerValues)
            {
                target.Add(current);
            }
        }

        private bool IsWildCardSubdomainMatch(string origin, CorsPolicy policy)
        {
            var actualOriginUri = new Uri(origin);
            var actualOriginRootDomain = GetRootDomain(actualOriginUri);

            foreach (var o in policy.Origins)
            {
                if (!o.Contains("*"))
                    continue;

                // 1) CANNOT USE System.Text.RegularExpression since it does not exist in .net platform 5.4 (which the Microsoft.AspNet.Cors project.json targets)
                // 2) '*' char is not valid for creation of a URI object so we replace it just for this comparison
                var allowedOriginUri = new Uri(o.Replace("*", "SOMELETTERS"));
                if (allowedOriginUri.Scheme == actualOriginUri.Scheme &&
                    actualOriginRootDomain == GetRootDomain(allowedOriginUri))
                    return true;
            }

            return false;
        }

        private string GetRootDomain(Uri uri)
        {
            //Got this snippet here http://stackoverflow.com/questions/16473838/get-domain-name-of-a-url-in-c-sharp-net
            var host = uri.Host;
            int index = host.LastIndexOf('.'), last = 3;

            while (index > 0 && index >= last - 3)
            {
                last = index;
                index = host.LastIndexOf('.', last - 1);
            }

            return host.Substring(index + 1);
        }
    }

    /// <summary>
    /// Needed to copy these in since some of them are internal to the Microsoft.AspNet.Cors project
    /// </summary>
    public static class CorsConstants
    {
        /// <summary>The HTTP method for the CORS preflight request.</summary>
        public static readonly string PreflightHttpMethod = "OPTIONS";
        /// <summary>The Origin request header.</summary>
        public static readonly string Origin = "Origin";
        /// <summary>
        /// The value for the Access-Control-Allow-Origin response header to allow all origins.
        /// </summary>
        public static readonly string AnyOrigin = "*";
        /// <summary>The Access-Control-Request-Method request header.</summary>
        public static readonly string AccessControlRequestMethod = "Access-Control-Request-Method";
        /// <summary>The Access-Control-Request-Headers request header.</summary>
        public static readonly string AccessControlRequestHeaders = "Access-Control-Request-Headers";
        /// <summary>The Access-Control-Allow-Origin response header.</summary>
        public static readonly string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
        /// <summary>The Access-Control-Allow-Headers response header.</summary>
        public static readonly string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
        /// <summary>The Access-Control-Expose-Headers response header.</summary>
        public static readonly string AccessControlExposeHeaders = "Access-Control-Expose-Headers";
        /// <summary>The Access-Control-Allow-Methods response header.</summary>
        public static readonly string AccessControlAllowMethods = "Access-Control-Allow-Methods";
        /// <summary>The Access-Control-Allow-Credentials response header.</summary>
        public static readonly string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
        /// <summary>The Access-Control-Max-Age response header.</summary>
        public static readonly string AccessControlMaxAge = "Access-Control-Max-Age";
        internal static readonly string[] SimpleRequestHeaders = new string[4]
        {
      "Origin",
      "Accept",
      "Accept-Language",
      "Content-Language"
        };
        internal static readonly string[] SimpleResponseHeaders = new string[6]
        {
      "Cache-Control",
      "Content-Language",
      "Content-Type",
      "Expires",
      "Last-Modified",
      "Pragma"
        };
        internal static readonly string[] SimpleMethods = new string[3]
        {
      "GET",
      "HEAD",
      "POST"
        };
    }
}
options.AddPolicy("MyCorsPolicy",
   builder => builder
      .SetIsOriginAllowedToAllowWildcardSubdomains()
      .WithOrigins("https://*.mydomain.com")
      .AllowAnyMethod()
      .AllowCredentials()
      .AllowAnyHeader()
      .Build()
   );
app.UseCors("MyCorsPolicy");
    using Microsoft.AspNetCore.Cors.Infrastructure;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using Microsoft.Extensions.Primitives;
    using System;
    using System.Text.RegularExpressions;

namespace Microsoft.AspNetCore.Cors.Infrastructure
{
    public class CORSServiceWildCardSupport : CorsService, ICorsService
    {
        private readonly CorsOptions _options;
        private readonly ILogger _logger;
        public CORSServiceWildCardSupport(IOptions<CorsOptions> options, ILoggerFactory loggerFactory) : base(options, loggerFactory)
        {
            _options = options.Value;
            _logger = loggerFactory.CreateLogger<CorsService>();
        }

        public new virtual CorsResult EvaluatePolicy(HttpContext context, CorsPolicy policy)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (policy == null)
            {
                throw new ArgumentNullException("policy");
            }
            if (policy.AllowAnyOrigin && policy.SupportsCredentials)
            {
                throw new ArgumentException(Resource.InsecureConfiguration, "policy");
            }
            IHeaderDictionary headers = context.Request.Headers;
            StringValues origin = headers[CorsConstants.Origin];

            bool num = string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase);
            bool flag = num && headers.ContainsKey(CorsConstants.AccessControlRequestMethod);

            CorsResult result = new CorsResult
            {
                IsPreflightRequest = flag,
                IsOriginAllowed = IsWildCardSubdomainMatch(origin, policy)
            };
            if (flag)
            {
                EvaluatePreflightRequest(context, policy, result);
            }
            else
            {
                EvaluateRequest(context, policy, result);
            }
            return result;
        }

        protected virtual IsWildCardSubdomainMatch(string origin, CorsPolicy policy)
        {
            var actualOrigin = new Uri(origin);
            foreach (var o in policy.Origins)
            {
                if (IsWildcardMatch(actualOrigin, o))
                {
                    return true;
                }
            }
            return false;
        }

        private bool IsWildcardMatch(Uri actualOrigin, string wildcardUri)
        {
            if (!wildcardUri.StartsWith(actualOrigin.Scheme))
            {
                return false;
            }
            var wildcardUriMinusScheme = wildcardUri.Replace(actualOrigin.Scheme + "://", "");
            var regexFirstStage = wildcardUriMinusScheme.Replace(".", "\\.");
            var regexAllowedHosts = "^" + regexFirstStage.Replace("*", ".*") + "$";
            var actualOriginMinusScheme = actualOrigin.OriginalString.Replace(actualOrigin.Scheme + "://", "");
            var isMatch = Regex.IsMatch(actualOriginMinusScheme, regexAllowedHosts);
            return isMatch;
        }
    }
}
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
namespace Microsoft.Extensions.DependencyInjection
{
    public static class CORSServiceCollectionExtensions
    {
        public static IServiceCollection AddCORSWithWildCardSupport(this IServiceCollection services)
        {
            if (services == null)
            {
                throw new ArgumentNullException("services");
            }
            services.AddOptions();
            services.TryAdd(ServiceDescriptor.Transient<ICorsService, CORSServiceWildCardSupport>());
            services.TryAdd(ServiceDescriptor.Transient<ICorsPolicyProvider, DefaultCorsPolicyProvider>());
            return services;
        }

        public static IServiceCollection AddCORSWithWildCardSupport(this IServiceCollection services, Action<CorsOptions> setupAction)
        {
            if (services == null)
            {
                throw new ArgumentNullException("services");
            }
            if (setupAction == null)
            {
                throw new ArgumentNullException("setupAction");
            }
            services.AddCORSWithWildCardSupport();
            services.Configure(setupAction);
            return services;
        }
    }
}
public void ConfigureServices(IServiceCollection services)
        {
            try
            {
                string[] whitelist = {"https:\\environment.modules.*.releaseversion.companyname.com","https:\\*.modules.*.releaseversion.companyname.com","https:\\environment.*.*.releaseversion.companyname.com"};

                services.AddCORSWithWildCardSupport(o => o.AddPolicy(Resource.CorsPolicyName, builder =>
                {
                    builder.WithOrigins(whitelist)
                           .AllowAnyMethod()
                           .AllowAnyHeader()
                           .AllowCredentials();
                }));

                services.AddControllers();

                services.AddMvc(option => option.EnableEndpointRouting = false)
                    .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

                services.AddAuthentication("Windows");
            }
            catch(Exception ex)
            {
                Logger.Error($"Failed to start due to {ex.Message}.");
            }
        }