Корс проблемы с Vue и Dotnet - PullRequest
       0

Корс проблемы с Vue и Dotnet

0 голосов
/ 07 декабря 2018


мои среды:

  • бэкэнд (localhost), написанный в .net web api 2
    с включенным пакетом "Microsoft.AspNet.WebApi.Cors"
  • внешний интерфейс (localhost) с vue-js-2 с webpack-simple
    vue-ресурс для http-запросов


У меня возникают некоторые проблемы с CORS, которыеЯ не могу решить:
Запуск «простых запросов» с помощью глагола GET работает, но при использовании глагола POST я получаю ошибку CORS, говоря:

Access to XMLHttpRequest at 'http://localhost:59837/api/Employees' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Я прочитал Ссылка на CORS в Mozilla и заметил, что действительно мой POST-запрос сначала отправляется как предварительный запрос с глаголом OPTIONS и заголовком Access-Control-Request-Method: POST.

в моем файле WebApiConfig , который у меня есть:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
           ...

            // Web API enable CORS
            System.Web.Http.Cors.EnableCorsAttribute cors = new System.Web.Http.Cors.EnableCorsAttribute("*", "*", "*");
            config.EnableCors(cors);
        }
    }

и мой код запроса POST выглядит следующим образом:

testPOST(){
      const credentials = { username: '1', password: '11'};
      this.$http.post('http://localhost:59837/api/Employees', {params: {id: '2'}, body: credentials, method: 'POST', headers: {'Content-Type': 'text/plain'}})
      .then(function (response){
          console.log(response);
      })
      .catch(function (error) {
          console.log(error);
      });
    }

и функция POST в контроллере:

public async Task<HttpResponseMessage> PostEmployees(Credentials creds)
        {

            Employees emp = await db.Employees.FindAsync(Int32.Parse(creds.username));

            if (emp.password.Equals(creds.password))
            {
                emp.password = "";
                return Request.CreateResponse(HttpStatusCode.OK, emp);
            }

            else
                return Request.CreateResponse(HttpStatusCode.Unauthorized, "Username or password are incorrect");            
        }

Я думал, что, возможно, мне нужно определить запрос POSTЗаголовки к авторизованному «text / plain».Используя Fiddler, я нашел исходящий запрос, но у него не было текстового / простого заголовка. Сейчас я даже не уверен, связана ли моя ошибка с конфигурацией бэкэнда или с методом отправки запроса веб-интерфейса.Кто-нибудь сталкивался с чем-нибудь подобным?(извините за весь код, я хотел быть как можно более всеобъемлющим, но минимальным)

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

Решение
Я думаю, что проблема на самом деле была связана как с интерфейсом, так и с фоном.
Учебник Microsoft по веб-API 2 , похоже, не упоминает о его недостаткеподдержки заголовка OPTIONS, который генерируется некоторыми клиентами в качестве запроса «перед полетом».Кроме того, параметры, которые я использовал в Vue-Resource, также вызывали некоторые проблемы.
Back-end :
1. Я изменил поведение по умолчанию, которое заставляло сервер отбрасывать все запросы с помощью OPTIONSзаголовок в Global.asax.cs , спасибо Obelixx :

if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
   {
    //Response.Flush();
    Response.StatusCode = 200;
    Response.AddHeader("Access-Control-Allow-Headers", "content-type,accept,authorization");
    Response.AddHeader("Access-Control-Allow-Origin", "*");
    Response.AddHeader("Access-Control-Allow-Credentials", "true");
    Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE");
    Response.AddHeader("Content-Type", "application/json");
    Response.AddHeader("Accept", "application/json");
    Response.End();
   }

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

2. как можно видеть здесь , я также добавилДействия OPTIONS в моем классе контроллера:

// OPTIONS: allow pre-flight
public HttpResponseMessage Options()
{
    return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}

front-end :
1. API vue-resource говорит, что имеет эту подпись для запроса POST:

post(url, [body], [config])

но также можно включить тело в параметре конфигурации.
хорошо, не работает для met.поэтому вместо этого:

this.$http.post('http://localhost:59837/api/Employees', 
{params: {id: '2'}, body: credentials, method: 'POST', headers: {'Content-Type': 'text/plain'}})

Я сделал это:

this.$http.post('http://localhost:59837/api/Employees', credentials, 
{headers: {'Content-Type': 'application/json'}})

обратите внимание, как я взял тело: учетные данные и просто использовал учетные данные в качестве отдельного аргумента.

2. Я также изменил заголовок «Content-Type» с text / plain на application / json (Microsoft говорит, что типы text / plain должны предотвращатьперед полетом, но это только привело к тому, что мой форматер json не смог выполнить синтаксический анализ учетных данных ).
----
Так что на данный момент это решение, как я уже говорил, что у меня есть исправления, связанные как с интерфейсом, так и с фоном, я не уверен, действительно ли было так много ошибок или просто еще не обнаруженныхЯ исправил во многих местах.
Надеюсь, это поможет другим людям.

0 голосов
/ 07 декабря 2018

Web Api 2 не отвечает на запрос OPTIONS.Вы можете добавить обработчик для этого.Вот как я это решил один раз.Создайте где-нибудь IHttpModule.Вот мой:

namespace AAWebSmartHouse.WebApi.Infrastructure.Modules
{
    using System.Web;

    public class OPTIONSVerbHandlerModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.BeginRequest += (sender, args) =>
            {
                var app = (HttpApplication)sender;

                if (app.Request.HttpMethod == "OPTIONS")
                {
                    app.Response.StatusCode = 200;
                    app.Response.AddHeader("Access-Control-Allow-Headers", "content-type,accept,authorization");
                    app.Response.AddHeader("Access-Control-Allow-Origin", "*");
                    app.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                    app.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE");
                    app.Response.AddHeader("Content-Type", "application/json");
                    app.Response.AddHeader("Accept", "application/json");
                    app.Response.End();
                }
            };
        }

        public void Dispose()
        {
        }
    }
}

И добавьте его в Web.config:

<modules>
  <!-- ... -->
  <add name="OPTIONSVerbHandlerModule" type="AAWebSmartHouse.WebApi.Infrastructure.Modules.OPTIONSVerbHandlerModule" />
</modules>
<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <!-- ... -->
</handlers>

Если он все еще не отвечает на запрос OPTIONS для какого-либо метода в вашем контроллере, я вижу, что ядобавили атрибут AcceptVerbs так:

// GET api/Account/UserInfo
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UserInfo")]
[AcceptVerbs("OPTIONS", "GET")]
public UserInfoViewModel GetUserInfo()
{
    ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

    return new UserInfoViewModel
    {
        Email = User.Identity.GetUserName(),
        HasRegistered = externalLogin == null,
        LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...