如何让 CORS 与 ASP.Net Core Web API 服务器 Angular 2 客户端一起工作

Posted

技术标签:

【中文标题】如何让 CORS 与 ASP.Net Core Web API 服务器 Angular 2 客户端一起工作【英文标题】:How to get CORS to work with ASP.Net Core Web API server Angular 2 client 【发布时间】:2017-04-08 04:33:42 【问题描述】:

我已经阅读了我能找到的关于 ASP.NET Core 和 CORS 的所有内容,并且我相信我了解其中的大部分内容,但是如果我能让它发挥作用,我会被诅咒的。我用的是Chrome浏览器,数据如下:

预检:

General:
Request URL:http://localhost:34376/api/login
Request Method:OPTIONS
Status Code:204 No Content
Remote Address:[::1]:34376

Response Headers:
view source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:access-control-allow-origin,content-type
Access-Control-Allow-Origin:http://localhost:3000
Date:Wed, 23 Nov 2016 03:05:00 GMT
Server:Kestrel
Vary:Origin
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcUHJvamVjdHNcbXZjXFNob3BVc1NlcnZpY2Vcc3JjXFNob3BVc1NlcnZpY2VcYXBpXGxvZ2lu?=

Request Headers:
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:access-control-allow-origin, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:34376
Origin:http://localhost:3000
Referer:http://localhost:3000/authentication
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/54.0.2840.71 Safari/537.36

帖子:

Request URL:http://localhost:34376/api/login
Request Method:POST
Status Code:500 Internal Server Error
Remote Address:[::1]:34376

Response Headers:
view source
Content-Length:0
Date:Tue, 22 Nov 2016 03:11:40 GMT
Server:Kestrel
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcUHJvamVjdHNcbXZjXFNob3BVc1NlcnZpY2Vcc3JjXFNob3BVc1NlcnZpY2VcYXBpXGxvZ2lu?=

Request Headers:
view source
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Access-Control-Allow-Origin:true
Connection:keep-alive
Content-Length:87
Content-Type:application/json
Host:localhost:34376
Origin:http://localhost:3000
Referer:http://localhost:3000/authentication
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36

Request Payload:
view source
userName: "", email: "irv@testing.com", password: "!P@ssw0rd", rememberMe: false
   email: "irv@testing.com"
   password: "!P@ssw0rd"
   rememberMe: false
   userName:""

ASP.NET Core 代码:

public void ConfigureServices(IServiceCollection services)

    services.AddCors(options => 
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials().Build() );
    );
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddMvc();


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseCors("CorsPolicy");

    app.UseApplicationInsightsRequestTelemetry();

    app.UseApplicationInsightsExceptionTelemetry();

    app.UseMvc();

ASP.NET Core 控制器:

[EnableCors("CorsPolicy")]
[Produces("application/json")]
[Route("api/Authentication")]
public class AuthenticationController : Controller

    private IUnitOfWork _unitOfWork;
    public AuthenticationController(IUnitOfWork unitOfWork)
    
        _unitOfWork = unitOfWork;
    

    [HttpPost]
    [Route("/api/login")]
    public JsonResult Login([FromBody]LoginInfo loginInfo)
    
        return Json(new  id_token = _unitOfWork.Users.CreateJwt(loginInfo) );
    

这是 Angular 代码:

@Injectable()
export class AuthenticationService 
private _currentAdminMode: boolean = false;

constructor(private _http: Http, private _config: ConfigurationService) 


public login(logInfo: LoginInfo): Observable<TokenContainer> 
    var headers = new Headers();
    headers.append('Content-Type', 'application/json');

    //return an observable
    return this._http.post(this._config.hostPrefix + '/api/login', JSON.stringify(logInfo),  headers: headers )
        .map((response) => 
            return <TokenContainer>(response.json());
        );

我在浏览器控制台中得到的确切错误是:

XMLHttpRequest cannot load http://localhost:34376/api/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500.

请注意,我从 POST 请求中收到 500 错误。如果出现 CORS 问题,这似乎不是服务器会发送的错误。我认为这是另外一回事,但是,所有这些代码都在单个域中工作,现在它是 CORS,有些事情正在变得混乱。无论如何,我已经阅读了我能找到的所有内容,但没有任何效果。我在想这可能与 WebAPI 路由有关。

感谢您提供的任何帮助!

【问题讨论】:

向 API 发出请求时遇到的确切错误是什么?您确定它们与 CORS 相关吗? 我从浏览器的控制台编辑了带有确切错误的问题。不知道问题出在哪里,我不知道如何进一步调试它。我在控制器操作方法上放置了一个断点,我可以告诉你我永远不会到达那个断点。谢谢! 您可以使用 Postman 或类似应用登录吗? 我用 Postman 得到了同样的结果,我刚试过....嗯 但是这个确切的服务器代码在单个域中工作(没有 CORS)虽然它也提供网页,但现在它不是 【参考方案1】:

嗯,我花了一天时间试图弄清楚如何处理几乎相同的问题。我将尝试描述更多信息:

我使用 netcoreapp1.0,基于 IIS 上的 WebAPI 的 RESTful 服务。前端:angular2。

在我的 Startup.cs 中:

// this is not much important, you can organize builder in Configure method, calling app.UseCors()
public void ConfigureServices(IServiceCollection services)
   
    services.AddCors(options =>
            
                options.AddPolicy("AllowSpecificOrigin",
                    builder => builder.WithOrigins("http://localhost:37885")
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials());
            );
    services.AddMvc();  
    services.Configure<MvcOptions>(options =>
    
        options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
    );


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    app.UseCors("AllowSpecificOrigin");
    app.UseMvc();    

当我在 Visual Studio 中运行这段代码时,它运行良好。但是,当我在 IIS 上发布我的 WebAPI 项目时,我遇到了麻烦:预检请求返回 Status "Code:204 No Content",而 POST 和 PUT 请求返回 “405 方法不允许”

当应用程序托管在 IIS 上时,AllowAnyMethod() 似乎没有任何效果,因为我们可以看到只允许 GET、HEAD、OPTIONS、TRACE从上图看。

为了测试这个东西并消除对 Angular 和 Web API 的怀疑,我创建了测试脚本并在 Chrome 开发者控制台中运行它:

var xmlHttp = new XMLHttpRequest(); //returns a XMLHttpRequest object
xmlHttp.open('PUT', "http://localhost:27895/api/usergroups/58c624eb54d98519e85c5771", true);
xmlHttp.setRequestHeader('Content-Type', "application/json");  
xmlHttp.send(JSON.stringify("id":"58c624eb54d98519e85c5771","Name":"Группа первооткрывателей"));

我从我的 Angular 客户端页面运行此脚本时遇到了同样的问题。比我从托管 WebApi 的同一来源运行此脚本(以检查没有 COR 的 webAPI)。我有一个错误,告诉我现场不允许使用 PUT 方法!

最后,我找到了解决方案:问题出在 IIS 上的 WebDAV 模块,与我的 RESTful 服务冲突。 我在 IIS 上从我的 webAPI 站点中删除了 WEBDAV 模块,现在它可以完美运行了:

为此:

    在 IIS 上选择您的 WebAPI 站点 打开“模块” 查找并删除 WebDAV 选项

也为您的 webApi 站点从 IIS 上的处理程序映射中删除 WebDAV 选项。

如果您想了解更多关于 WEBDAV 和 Web API 冲突的说明,这些主题会很有用:

forum iis.net, forum asp.net


事实证明,WebDav 处理程序和模块在下一次发布后再次出现在 IIS 中。因此,为了防止站点这样做,请修改您的 WebAPI 应用程序的 web.config,如下所示:

<handlers>
   <remove name="WebDAV" />
</handlers>
<modules>
   <remove name="WebDAVModule" />
</modules>

this topic 帮我弄明白了。

【讨论】:

我已经编辑了答案:添加了有关 web.config 首选项的信息 6 小时后,我来到了这里。你的回答拯救了我的学业。谢谢

以上是关于如何让 CORS 与 ASP.Net Core Web API 服务器 Angular 2 客户端一起工作的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET Core 中启用 CORS

如何在 Asp.Net Core 3.0 WebAPI 中启用 CORS

ASP.NET Core AWS 无服务器和 CORS

如何使用 ASP.NET Core 解决 REACT 中的 CORS 错误

ASP.NET Core Web Api 发送 Access-Control-Allow-Origin: null CORS header and chrome 出错,如何解决?

如何在 ASP.net Core WebAPI 中启用 CORS