如何使用.NET Core 2配置Angular 6以允许来自任何主机的CORS?

sea*_*t13 5 cors asp.net-core angular

我有一个在4200上本地运行的简单Angular App,我正在测试使用.net core在5000上本地运行的Web API。我的startup.cs具有正确配置的CORS以允许我相信的所有内容。

在ConfigureServices部分中,我有: services.AddCors();

在配置部分中,我有:

app.UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());

但是,当我尝试打我的webapi时,我仍然在浏览器中得到它。

来自源' http:// localhost:4200 '的信息已被CORS策略阻止:对预检请求的响应未通过访问控制检查:不允许对预检请求进行重定向。

我查看了其他答案,它们似乎都具有我尝试没有改变的这种或类似的变化。不知道我还需要做什么?

Ran*_*dis 8

可能的问题:

  • 在您的startup.cs.Configure()方法中,app.UseCors()先行app.useMVC()吗?
  • Http请求URL是否包含斜杠(/)
  • Http请求是否包含凭据?
  • 浏览器是否从API接收到Http响应?
  • 响应中是否包含“ Access-Control-Allow-Origin”标头?
  • 当您从Postman发送请求时,Http响应中是否包含“ Access-Control-Allow-Origin”标头以及包含数据的正文?

陷阱

Firefox要求为您的API安装证书,以便使用HTTPS协议发送Http请求。

使用Postman和浏览器开发人员工具测试您的API。注意2 Http请求。Http 200是“预检”,可以查看可用的CORS选项。

  • 如果您的API(.NET)抛出HTTP 500 (Internal Server Error),它将返回开发人员异常页面,而Postman将显示一条“no ‘Access-Control-Allow-Origin’ header is present on the requested resource”消息- 这是误导性的
  • 在这种情况下,实际的问题是开发人员例外页面无法从服务器返回到在不同Origin上运行的客户端(浏览器)。

指出以下几点:

  • 所述CORS规范指出起源设置为“*”(所有来源)是无效的,如果所述接入控制允许证书标头存在。
  • AllowAnyOrigin() 建议不要在生产环境中使用它,除非您打算允许任何人使用您的API并且您将不会实现凭据。
  • EnableCors使用多个CORS策略时,您无需在控制器级别使用属性配置CORS 。
  • 使用ASP.NET Core配置多个CORS策略很容易(请参见下面的教程

以下文章值得回顾:

ASP.NET Core 2.2不允许使用AllowAnyOrigin()允许凭据

在ASP.NET Core中启用跨域请求(CORS)

关键点(tldr;):

  • CORS中间件必须在您的应用程序配置中定义的所有终结点之前。
  • 必须指定的URL不带斜杠(/)
  • 如果浏览器发送凭据,但响应中不包含有效的Access-Control-Allow-Credentials标头,则浏览器不会将响应公开给应用程序,并且跨域请求失败。
  • CORS规范还指出,如果存在Access-Control-Allow-Credentials标头,则将原点设置为“ *”(所有原点)是无效的。
  • 如果浏览器支持CORS,则会为跨域请求自动设置这些标头。
  • 如果响应中不包含Access-Control-Allow-Origin标头,则跨域请求将失败。

CORS教程:(2)Angular客户端+ ASP.NET Core

  1. 创建Visual Studio解决方案

    md c:\ s \ a
    cd c:\ s \ a
    c:\ s \ a> dotnet新sln -n solutionName
    
  2. 创建ASP.NET Core项目

    c:\ s \ a> md s
    c:\ s \ a> cd s
    c:\ s \ a \ s> dotnet新的webapi -o api -n api
    
  3. API启动设置和CORS配置

launchSettings.json

将开发配置文件克隆到暂存配置文件

{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iis": {
    "applicationUrl": "http://localhost:myIISApiPortNumber",
    "sslPort": myIISApiSSLPortNumber
},
"iisExpress": {
    "applicationUrl": "http://localhost:myIISExpressApiPortNumber",
    "sslPort": myIISExpressApiSSLPortNumber
}
},
"profiles": {
"Development (IIS Express)": {
    "commandName": "IISExpress",
    "launchBrowser": true,
    "launchUrl": "api/values",
    "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Development"
    }
},
"Staging (IIS Express)": {
    "commandName": "IISExpress",
    "launchBrowser": true,
    "launchUrl": "api/values",
    "applicationUrl": "https://localhost:myIISExpressApiSSLPortNumber;http://localhost:myIISExpressApiPortNumber",
    "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Staging"
    }
},
"Production (IIS)": {
    "commandName": "IIS",
    "launchBrowser": true,
    "launchUrl": "api/values",
    "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Production"
    },
    "applicationUrl": "https:localhost:myIISApiSSLPortNumber;http://localhost:myIISApiPortNumber"
}
}
}
Run Code Online (Sandbox Code Playgroud)

startup.cs

添加CORS配置

public class Startup
{
    public IConfiguration Configuration { get; }

    public IServiceCollection _services { get; private set; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        _services = services;
        RegisterCorsPolicies();
        services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseCors("DevelopmentCorsPolicy");
            app.UseDeveloperExceptionPage();
        }
        else if (env.IsStaging())
        {
            app.UseCors("StagingCorsPolicy");
        }
        else
        {
            app.UseCors("ProductionCorsPolicy");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMvc(); // CORS middleware must precede any defined endpoints
    }

    private void RegisterCorsPolicies()
    {
        string[] localHostOrigins = new string[] {
        "http://localhost:4200", "http://localhost:3200"};

        string[] stagingHostOrigins= new string[] {
        "http://localhost:4200"};

        string[] productionHostOrigins = new string[] {
        "http://yourdomain.net", "http://www.yourdomain.net",
        "https://yourdomain.net", "https://www.yourdomain.net"};

        _services.AddCors(options =>    // CORS middleware must precede any defined endpoints
        {
            options.AddPolicy("DevelopmentCorsPolicy", builder =>
            {
                builder.WithOrigins(localHostOrigins)
                        .AllowAnyHeader().AllowAnyMethod();
            });
            options.AddPolicy("StagingCorsPolicy", builder =>
            {
                builder.WithOrigins(stagingHostOrigins)
                        .AllowAnyHeader().AllowAnyMethod();
            });
            options.AddPolicy("ProductionCorsPolicy", builder =>
            {
                builder.WithOrigins(productionHostOrigins)
                        .AllowAnyHeader().AllowAnyMethod();
            });
        //options.AddPolicy("AllowAllOrigins",
        //    builder =>
        //    {
        // WARNING: ASP.NET Core 2.2 does not permit allowing credentials with AllowAnyOrigin() 
        // cref: https://docs.microsoft.com/en-us/aspnet/core/migration/21-to-22?view=aspnetcore-2.2&tabs=visual-studio
            //        builder.AllowAnyOrigin()
            //               .AllowAnyHeader().AllowAnyMethod();
            //    });
            //options.AddPolicy("AllowSpecificMethods",
            //    builder =>
            //    {
            //        builder.WithOrigins(productionHostOrigins)
            //               .WithMethods("GET", "POST", "HEAD");
            //    });
            //options.AddPolicy("AllowSpecificHeaders",
            //    builder =>
            //    {
            //        builder.WithOrigins(productionHostOrigins)
            //               .WithHeaders("accept", "content-type", "origin", "x-custom-header");
            //    });
            //options.AddPolicy("ExposeResponseHeaders",
            //    builder =>
            //    {
            //        builder.WithOrigins(productionHostOrigins)
            //               .WithExposedHeaders("x-custom-header");
            //    });
            //options.AddPolicy("AllowCredentials",
            // WARNING: ASP.NET Core 2.2 does not permit allowing credentials with AllowAnyOrigin() cref: https://docs.microsoft.com/en-us/aspnet/core/migration/21-to-22?view=aspnetcore-2.2&tabs=visual-studio
            //    builder =>
            //    {
            //        builder.WithOrigins(productionHostOrigins)
            //               .AllowCredentials();
            //    });
            //options.AddPolicy("SetPreflightExpiration",
            //    builder =>
            //    {
            //        builder.WithOrigins(productionHostOrigins)
            //               .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
            //    });
        });
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 使用开发(IIS Express)配置文件启动调试API

设置断点 ValuesController.Get()

  1. 使用Postman测试API:

    https://localhost:myApiPortNumber/api/values

    • Access-Control-Allow-Origin标头和值应作为响应
  2. 创建Angular应用程序

    c:\ s \ a \ s> ng new Spa1 --routing(将自动创建Spa文件夹)
    
  3. 启动Spa1应用程序

    c:\ s \ a \ s> cd Spa1
    c:\ s \ a \ s \ Spa1> NG服务
    
  4. 浏览到http:// localhost:4200 /

    • Spa1应该成功启动
  5. 在Spa1中实施COR

app.module.ts

  • 导入HttpClientModule
import { HttpClientModule } from '@angular/common/http';

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

app.component.ts

  • 导入HttpClient

  • getValues()使用CORS请求添加方法

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnInit {
  title = 'Spa1';
  values: any;
  apiUrl: string = environment.apiUrl;
  valuesUrl = this.apiUrl + "values";

  constructor(private http: HttpClient) { }

  ngOnInit() {
    this.getValues();
  }
  getValues() {
    this.http.get(this.valuesUrl).subscribe(response => {
      this.values = response;
  }, error => {
  console.log(error);
});
}
}
Run Code Online (Sandbox Code Playgroud)

app.component.html

<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
</div>
<h2>Values</h2>
<p *ngFor="let value of values">
  {{value}}
</p>
<router-outlet></router-outlet>
Run Code Online (Sandbox Code Playgroud)

环境

export const environment = {
  production: false,
  apiUrl: 'https://localhost:myApiPortNumber/api/'
};
Run Code Online (Sandbox Code Playgroud)
  1. 启动Spa1应用程序

    c:\ s \ a \ s \ Spa1> NG服务
    
  2. 浏览到http:// localhost:4200 /

    • Chrome&Edge:应立即成功发出COR请求
    • Safari:我尚未测试
    • Firefox:由于证书不受信任,可能会阻止请求。

修复Firefox块的一种方法:

FireFox | 选项| 隐私和安全| 安全性 证书| [查看证书]:

证书管理器| [添加例外]:

   add localhost
Run Code Online (Sandbox Code Playgroud)

CORS测试

  1. 克隆Spa1

    c:\ s \ a \ s> xcopy / s / i Spa1 Spa2
    
  2. 重构Spa2的标题

app.component.ts

export class AppComponent implements OnInit {
  title = 'Spa2';
}
Run Code Online (Sandbox Code Playgroud)
  1. 端口3200上启动Spa2应用程序

    c:\ s \ a \ s \ Spa2> ng服务--port 3200
    
  2. 浏览到http:// localhost:3200 /

    • values数组应在网页上呈现
  3. 使用开发(IIS Express)配置文件停止调试API

  4. 使用暂存(IIS Express)配置文件启动调试API

  5. 浏览到http:// localhost:4200 /

    • values数组应呈现在网页上。
  6. 浏览到http:// localhost:3200 /

    • values数组不应在网页上呈现
  7. 使用开发人员工具检查Http响应:

    • Access-Control-Allow-Origin标头和值不应作为响应


Kri*_*han 7

在方法 ConfigureServices 中添加以下代码片段。编辑此项以仅允许自定义标题。

// Add service and create Policy with options
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
                );
        });
Run Code Online (Sandbox Code Playgroud)

在Configure方法中添加以下内容

app.UseCors("CorsPolicy");
Run Code Online (Sandbox Code Playgroud)

将“EnableCors”属性添加到控制器。

[EnableCors("CorsPolicy")]
Run Code Online (Sandbox Code Playgroud)