【问题标题】:No 'Access-Control-Allow-Origin' in header error标头错误中没有“Access-Control-Allow-Origin”
【发布时间】:2018-09-19 00:22:39
【问题描述】:

我正在使用带有 asp.net 核心后端的 Angular 2 应用程序。我正在尝试打印 pdf(下面的客户端代码)。当我在我们的开发服务器上运行时,一切正常;但是,在生产中运行我得到了

加载 api_url 失败:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问原始 url。

我所看到的所有内容都提到了有关 CORS 策略的内容,但我不明白这如何在一台服务器上正常工作,而在另一台服务器上却不行。此外,在访问其他 API 端点时,它似乎可以正常检索。

客户端api调用:

getPDF(pickupId: string): void {
    this.printingSub.next(true);
    this._http.get(this._dataUrl + 'pickupsheet?pickupid=' + pickupId + '&barcode=true', { responseType: ResponseContentType.Blob })
        .catch(error => this.handleError(error))
        .subscribe((response: Response) => {
            this.pdfBlob = new Blob([response.blob()], { type: 'application/pdf' });
            const blobUrl = URL.createObjectURL(this.pdfBlob);
            const iframe = document.createElement('iframe');
            iframe.style.display = 'none';
            iframe.src = blobUrl;
            document.body.appendChild(iframe);
            iframe.contentWindow.print();
            this.printingSub.next(false);
        });
}

Startup.cs

public class Startup
{
    public IConfiguration Configuration { get; }
    public IConfigurationSection AppSettings { get; }

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile(@"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
        AppSettings = Configuration.GetSection("appSettings");
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        ConfigureDatabase();
        ConfigurePolicies(services);

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddOptions();
        services.Configure<AppAccessSettings>(s =>
        {
            s.Env = AppSettings.GetSection("env").Value;
            s.EnableAuth = bool.Parse(AppSettings.GetSection("enableAuth").Value);
        });

        services.AddMvc().AddJsonOptions(options =>
            options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver()
        );
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        // Configure JWT authentication
        Authentication.SetVarFromFile(AppSettings.GetSection("authFile").Value);
        Authentication.SetAuth(ref app, AppSettings.GetSection("audience").Value);
        app.UseCors("CorsPolicy");
        app.UseMvc();
    }

    private void ConfigureDatabase()
    {
        string dbSource = AppSettings.GetSection("env").Value;
        OracleEnv.Connection = Configuration.GetSection("connectionStrings").GetSection(dbSource).Value;
    }

    private void ConfigurePolicies(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });

        services.AddAuthorization(options =>
        {
            options.AddPolicy("EnableAuth",
                policy => policy.Requirements.Add(new AuthRequirement(Configuration)));
        });

        services.AddSingleton<IAuthorizationHandler, UserAuthHandler>();
    }
}

private void ConfigurePolicies(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });

        services.AddAuthorization(options =>
        {
            options.AddPolicy("EnableAuth",
                policy => policy.Requirements.Add(new AuthRequirement(Configuration)));
        });

        services.AddSingleton<IAuthorizationHandler, UserAuthHandler>();
    }

Pickup Sheet API 方法

[Route("PickupSheet")]
    public IActionResult GetPickupSheet(string pickupId, bool barCode)
    {
        PbReportGenerator rpt = new PbReportGenerator();
        byte[] report = rpt.RetrievePDFReport(232, new Dictionary<string, string>
        {
            { pickupId, "string" },
            { (barCode ? 1 : 0).ToString(), "int" }
        });

        var stream = new MemoryStream(report);
        var response = File(stream, "application/pdf", String.Format("Report232_{0}.pdf", pickupId)); 

        return response;
    }

【问题讨论】:

  • 好吧,CORS 是服务器端的,所以你必须展示你是如何在那里配置它的。
  • 能分享一下pickupsheet api方法吗
  • 发布整个 startup.cs。我想 UseCors 被调用太晚了。
  • 我已经发布了启动代码。这在开发服务器和本地(邮递员)上运行良好。这只是我遇到问题的生产服务器。
  • 我的经验不足在这方面占了上风。事实证明,来自浏览器的错误具有误导性(真是令人惊讶)。我错过了报告的 pdf 版本在生产中导出到的文件夹。

标签: asp.net-core cors


【解决方案1】:

您需要为每个请求设置withCredentials

this._http.get(URL, { responseType: ResponseContentType.Blob, withCredentials: true })

【讨论】:

  • 为什么有必要这样做?
  • @Mardoxx 可能是因为(如果它类似于fetch),这就是请求知道发送 cookie 的方式。
猜你喜欢
  • 1970-01-01
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 2017-09-19
  • 2015-04-02
  • 2020-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多