【问题标题】:Getting an error "blocked by CORS policy" only for "https://localhost:44361/connect/token" in Angular 7 web app仅在 Angular 7 Web 应用程序中为“https://localhost:44361/connect/token”获取错误“被 CORS 策略阻止”
【发布时间】:2019-02-04 05:31:00
【问题描述】:

完全错误如下图。

Access to XMLHttpRequest at 'https://localhost:44361/connect/token' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我在 .net core web api 的启动类中启用了核心策略,如下所示。

我的 ConfigureService 方法

        public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        services.AddDbContext<LEAFDDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), builder =>
        {
            builder.EnableRetryOnFailure(5, TimeSpan.FromSeconds(10), null);
        }));

        services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<LEAFDDbContext>()
                .AddDefaultTokenProviders();

        services.AddCors(options =>
        {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });
        Installer.ConfigureServices(services);
        //services.AddCors();
        //services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        //services.AddSingleton<IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>();


        //services.AddAuthentication(options =>
        //{
        //    //options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //    //options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //    //options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        //    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        //})
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.Events.OnRedirectToLogin = ctx =>
            {
                // if it is an ajax/api request, don't redirect
                // to login page.
                if (!(IsAjaxRequest(ctx.Request) || IsApiRequest(ctx.Request)))
                {
                    ctx.Response.Redirect(ctx.RedirectUri);
                    return Task.CompletedTask;
                }
                ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
                return ctx.Response.WriteAsync("Unauthorized");
            };
        })
        .AddOAuthValidation()
        //services.AddAuthentication()
        .AddOpenIdConnectServer(options =>
        {
            options.Provider = new AuthorizationProvider();

            // Enable the authorization and token endpoints.
            options.AuthorizationEndpointPath = "/connect/authorize";
            options.TokenEndpointPath = "/connect/token";
            options.AllowInsecureHttp = true;

            // Note: to override the default access token format and use JWT, assign AccessTokenHandler:
            //
            options.AccessTokenHandler = new JwtSecurityTokenHandler
            {
                InboundClaimTypeMap = new Dictionary<string, string>(),
                OutboundClaimTypeMap = new Dictionary<string, string>()
            };

            //
            // Note: when using JWT as the access token format, you have to register a signing key.
            //
            // You can register a new ephemeral key, that is discarded when the application shuts down.
            // Tokens signed using this key are automatically invalidated and thus this method
            // should only be used during development:
            //
            options.SigningCredentials.AddEphemeralKey();
            //
            // On production, using a X.509 certificate stored in the machine store is recommended.
            // You can generate a self-signed certificate using Pluralsight's self-cert utility:
            // https://s3.amazonaws.com/pluralsight-free/keith-brown/samples/SelfCert.zip
            //
            //options.SigningCredentials.AddCertificate("7D2A741FE34CC2C7369237A5F2078988E17A6A75");

        });

    }

配置方法

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }
        //app.UseOAuthValidation();
        app.UseAuthentication();
        app.UseMvc();

        app.UseMiddleware();

        app.UseCors("CorsPolicy");
        //app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
        app.UseWelcomePage();


    }

除 'https://localhost:44361/connect/token' 之外的所有其他调用都按预期工作:获取令牌时。

我正在将来自 Angular 7 网络应用程序的所有请求发送到 .net 核心网络 API。

作为一种解决方法,我从 google chrome 安装了跨域资源共享扩展,我需要更改代码级别来永久解决此问题。

【问题讨论】:

  • addCors()useCors() 应始终位于 addMvc()useMvc() 之前
  • @HarunCerim 这不能解决我的问题。无论如何,我想出了一个解决方案,并在下面提供了我的问题的答案。

标签: asp.net-core asp.net-core-webapi openid-connect angular7


【解决方案1】:

这是我想出的最终解决方案。

我没有直接从 Angular 7 应用程序调用“https://localhost:44361/connect/token”,而是在 API 控制器中创建了一个方法,该方法将调用上述调用并获取令牌。所以当我需要的时候,我只需要在 API 控制器中调用新创建的方法。

新建api调用如下

        [HttpPost]
    [Route("/api/[controller]/Token")]
    [EnableCors("CorsPolicy")]
    public async Task<ContentResult> Token(LoginTokenRequestModel model)
    {
        string UserId = string.Empty;
        try
        {
            using (HttpClient httpClient = new HttpClient())
            {
                if (!String.IsNullOrEmpty(model.Email))
                {

                    var content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]{
                         new KeyValuePair<string, string>("grant_type", model.grant_type),
                         new KeyValuePair<string, string>("client_secret", model.client_secret),
                         new KeyValuePair<string, string>("client_id", model.client_id),
                         new KeyValuePair<string, string>("username", model.Email),
                         new KeyValuePair<string, string>("password", model.Password),
                    });
                    string apiURL = "https://localhost:44361";

                    var response = await httpClient.PostAsync(apiURL + "/connect/token", content);
                    var resultContent = await response.Content.ReadAsStringAsync();

                    if (response.IsSuccessStatusCode)
                    {
                        var token = JsonConvert.DeserializeObject<object>(resultContent);
                        return new ContentResult
                        {
                            Content = token.ToString(),
                            ContentType = "text/plain",
                            StatusCode = 200
                        };
                    }

                    return new ContentResult
                    {
                        Content = JsonConvert.DeserializeObject<object>(resultContent).ToString(),
                        ContentType = "text/plain",
                        StatusCode = 200
                    };
                }
            }
        }

        catch (Exception ex)
        {
            return new ContentResult
            {
                Content = ex.Message,
                ContentType = "text/plain",
                StatusCode = 400
            };
        }
        return new ContentResult
        {
            Content = "",
            ContentType = "text/plain",
            StatusCode = 400
        };

    }

这解决了我的问题。

【讨论】:

    【解决方案2】:

    使用app.UseCors() 之前 app.useMvc()。当涉及到中间件调用时,顺序很重要。就个人而言,我将其保存在环境确定if-else

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseCors("CorsDevPolicy");
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
    
            app.UseHttpsRedirection();
            app.UseMiddleware(typeof(ErrorHandlingMiddleware));
            app.UseMvc();
        }
    

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 2019-08-04
      • 2019-11-16
      • 2020-02-15
      • 2019-06-26
      • 2020-07-14
      • 2020-10-31
      • 2021-12-25
      • 2021-04-01
      相关资源
      最近更新 更多