Запрещен перекрестный запрос - приложение построено с использованием Angular и ASP.NET Core - PullRequest
0 голосов
/ 31 мая 2018

Я создаю веб-сайт с Angular и ASP.NET Core.

На некоторых страницах я хочу получать данные из веб-API.Когда я запускаю приложение, браузер (Firefox) показывает, что

Запрос перекрестного источника заблокирован: одна и та же политика происхождения запрещает чтение удаленного ресурса в ... (URL) (причина: отсутствует токен)'authorization' в заголовке CORS (Access-Control-Allow-Headers 'из канала предварительной проверки CORS).

Я пробовал другие браузеры, получил ту же ошибку.

Для рассмотрения полномочий,Я использую HttpInterceptor для вставки заголовка авторизации для каждого запроса от внешнего интерфейса Angular.

Затем я заглянул в свой бэкэнд ASP.NET Core.Я установил политику CORS как app.UseCors(builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); }); , но она по-прежнему не работает.

Я проверил API с почтальоном, он отлично работает.

Где что-то не так?

Файл Startup.cs.

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

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().AddJsonOptions(
            opt => opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
            );

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });

        services.AddEntityFrameworkSqlServer();
        services.AddCors();
        services.AddSignalR();

        services.AddDbContext<ApplicationDbContext>(opt =>
        {
            opt.UseSqlServer(Configuration.GetConnectionString("Remote"));
        });

        services.AddIdentity<ApplicationUser, IdentityRole>(opts =>
        {
            opts.Password.RequireDigit = true;
            opts.Password.RequireLowercase = true;
            opts.Password.RequireUppercase = true;
            opts.Password.RequireNonAlphanumeric = false;
            opts.Password.RequiredLength = 7;
        }).AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddAuthentication(opts =>
        {
            opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(cfg =>
        {
            cfg.RequireHttpsMetadata = false;
            cfg.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer = Configuration["Auth:Jwt:Issuer"],
                ValidAudience = Configuration["Auth:Jwt:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"])),
                ClockSkew = TimeSpan.Zero,
                RequireExpirationTime = true,
                ValidateIssuerSigningKey = true,
                ValidateAudience = true
            };
        });

        services.AddAuthorization(options =>
        {
            options.AddPolicy("NonUser", policy => policy.RequireRole("RestrauntOwner", "RestrauntAdmin", "SystemAdmin"));
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
        app.UseCors(builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); });
        app.UseStaticFiles();
        app.UseSpaStaticFiles();
        app.UseAuthentication();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });
        app.UseSignalR(route =>
        {
            route.MapHub<OrderHub>("/orderhub");
        });
        app.UseCookiePolicy();
        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }
}

Это странно.Я разработал это на моем ПК с Windows в течение некоторого времени.Я клонировал проект на своем MacBook, он отлично работал без проблем на macOS.

Ответы [ 3 ]

0 голосов
/ 01 июня 2018

OK.Я обнаружил, что не так, это довольно глупо.

Я спросил поставщика веб-API.Он сказал мне, что это потому, что заголовок авторизации не был разрешен.

Я использую HttpIntercepter, чтобы вставить заголовок авторизации в каждый запущенный запрос формы Angular.Я сделал это, чтобы мой ASP.NET Core Web API мог аутентифицировать пользователей сайта.Но открытый веб-API не позволяет этот заголовок.

Он работает, если я не зашел на свой сайт, но если я выполню процедуру входа в систему, он получит токен и вставит авторизацию взапрос, и он запустит предварительный запрос OPTIONS, ну, тогда запрос будет заблокирован.

Такой глупый вопрос :) Я должен найти новый способ сделать это.

0 голосов
/ 22 августа 2018

Если вы не можете заставить его работать, вот пара советов:

Ваш источник должен точно соответствовать тому, что отправляет браузер.

  • Если это HTTPВы должны поставить HTTP, и HTTPS должен быть HTTPS.

  • Номер порта также должен быть указан и указан правильно.

    http://localhost:5000

    https://localhost:5001

  • Поэтому не устанавливайте правило CORS для "http://localhost:5001", если выВы используете вышеуказанные настройки, потому что это не тот же URL!

  • Посмотрите в браузере или Fiddler, чтобы получить все правильно и убедитесь, что это то, что вы ожидаете.При переключении между HTTP и HTTPS очень легко запутаться.

    enter image description here

Вы получите 204 с пустым ответом, еслито, что вы отправляете, не соответствует

  • Он не предоставит вам правильные данные, которые он ожидает, если вы ошибетесь

Заголовки НЕ чувствительны к регистру

  • Вы можете поставить "authorization" или "Authorization" или "aUtHoRiZaTiOn", если хотите.

Вы ДОЛЖНЫ включать методы, а также заголовки

  • Если вы не укажете разрешенные методы HTTP, используя WithMethods или AllowAnyMethod, это не сработает.Это очень легко пропустить - особенно для простого запроса GET.

Если вы используете промежуточное ПО или разветвленный конвейер MVC, вы можете добавить CORS на этом уровне.

Для app.UseSpa (если вы используете механизм хостинга Microsoft для SPA), вы можете сделать это

        app.UseSpa(spa =>
        {
            // see https://go.microsoft.com/fwlink/?linkid=864501

            // CORS just for the SPA
            spa.ApplicationBuilder.UseCors(builder =>
            {
                // Must specify Methods
                builder.WithMethods("GET");

                // Case insensitive headers
                builder.WithHeaders("AuthoriZatioN");

                // Can supply a list or one by one, either is fine
                builder.WithOrigins("http://localhost:5000");
                builder.WithOrigins("https://localhost:5001");
            });

Fiddler полезен

Fiddler покажет вам необходимые условия для успеха CORS.Здесь это заголовок authorization и метод GET.

Вы можете нажать R для предыдущего запроса, чтобы выполнить его повторно после изменения конфигурации сервера.Таким образом, вам не нужно постоянно запускать браузер.

Обязательно посмотрите Headers в разделе ответов, потому что фактическое содержимое будет 0 байт, даже в случае успеха.

enter image description here

0 голосов
/ 31 мая 2018

Причина этой ошибки: ваш клиентский проект и webapi находятся в другом домене (или порту).

Безопасность браузера не позволяет веб-странице отправлять запросы AJAX в другой домен.Это ограничение называется политикой того же происхождения и не позволяет вредоносному сайту считывать конфиденциальные данные с другого сайта.

Чтобы настроить CORS для своего приложения, добавьте в свой проект пакет Microsoft.AspNetCore.Cors .

Затем Включение CORS с промежуточным ПО: при запуске> ConfigureServicesmethod

    //For any origin
    public void ConfigureServices(IServiceCollection services)
    {
         services.AddCors(options =>
         {
            options.AddPolicy("AllowSpecificOrigin",
                builder1 => builder1.WithOrigins("http://web.user.local:44352"));
        });
    }

И в Configure метод:

      public void Configure(IApplicationBuilder app)
      {          

            // Shows UseCors with named policy.
            app.UseCors("AllowSpecificOrigin");

            //...rest
      }

Примечание: URL должен быть указан без завершающей косой черты (/).Если URL заканчивается на /, сравнение вернет false и заголовок не будет возвращен.

Для получения дополнительной информации читайте здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...