Получение ошибки «заблокировано политикой CORS» только для «https://localhost:44361/connect/token" в веб-приложении Angular 7» - PullRequest
0 голосов
/ 04 февраля 2019

Полная ошибка приведена ниже.

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, как показано ниже.

My ConfigureServicemethod

        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 core web api.

В качестве обходного пути я установил расширение для общего доступа к ресурсам из Google Chrome.и мне нужно изменение уровня кода, чтобы навсегда решить эту проблему.

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Используйте 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();
    }
0 голосов
/ 04 февраля 2019

Это окончательное решение, которое я придумал.

Вместо вызова "https://localhost:44361/connect/token" напрямую из приложения Angular 7, я создал метод в контроллере 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
        };

    }

Это решило мою проблему.

...