Войдите через AJAX, используйте cookie в MVC + Angular. КОРС

Мне нужно отделить aspnetboilerplate (интерфейс Asp.Net MVC + AngularJS) Web от части API и одновременно аутентифицировать пользователей в AngularJS + ASP.Net MVC. Это работает на одном домене. Не работает, когда API размещен на другом сервере.

Мое действие MVC AccountController Логин:

AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberMe }, identity);
return Json(new AjaxResponse {Success = true, TargetUrl = Request.ApplicationPath });

Мой файл Login.js:

    $("#LoginButton").click(function(e) {
        e.preventDefault();
        abp.ui.setBusy(
            $("#LoginArea"),
            abp.ajax({
                url: "http://internallyAccesibleServer/Account/Login",
                //url: abp.appPath + "Account/Login",
                type: "POST",
                crossDomain: true,
                data: JSON.stringify({
                    tenancyName: $("#TenancyName").val(),
                    usernameOrEmailAddress: $("#EmailAddressInput").val(),
                    password: $("#PasswordInput").val(),
                    rememberMe: false
                })
            })
            .done(function(response) {
                abp.message.info("Login succeeded");})
            .fail(function(data) {
                abp.message.error(data.details, data.message);
            })
        );
    });

Когда я запускаю это на hxxp://internallyAccesibleServer/ - вход в систему завершается успешно, и я могу получить доступ к авторизованным ресурсам через AngularJS. Если я запускаю один и тот же код Login.js с любого другого сервера — я на мгновение вижу сообщение «Вход выполнен успешно» (также я вижу запись в базе данных/журнале на моем internallyAccesibleServer — поэтому запрос AJAX работает нормально ), а затем приходит HTTP-ответ 302, ведьма преобразуется из 401 фреймворком MVC, а URL-адрес в заголовке Location — «hxxp://otherserver/account/login» — таким образом, источник запроса.

Мой Web.config о CORS:

<httpProtocol>
    <customHeaders>
       <add name="Access-Control-Allow-Origin" value="*" />
       <add name="Access-Control-Allow-Methods" value="GET, POST, HEAD, OPTIONS" />
       <add name="Access-Control-Allow-Headers" value="Content-Type, x-xsrf-token" />
    </customHeaders>
 </httpProtocol>  

Я считаю, что это как-то связано с обменом файлами cookie между AJAX и MVC. Может ли кто-нибудь помочь мне решить эту проблему, или я должен начать переписывать графический интерфейс в полном Angular без каких-либо представлений MVC Razor и использовать другой тип аутентификации, например Bearer? Полное приложение уже разработано с использованием представлений Razor :-(

Я прочитал все соответствующие сообщения forum.aspnetboilerplate.com, но на этот вопрос нет ответов. Извините, если срок действия ссылок истечет - добавление названия темы для справки.

РАСПРОСТРАНЕННЫЙ САЙТ WEBAPI И MVC hxxps://forum.aspnetboilerplate.com/viewtopic.php?f=2&t=871

РАЗВЕРНУТЬ ABP НА 3-Х УРОВНЕ hxxps://forum.aspnetboilerplate.com/viewtopic.php?f=2&t=2376

3-УРОВНЕВОЕ РАЗВЕРТЫВАНИЕ. ОТДЕЛЬНЫЙ ГРАФИЧЕСКИЙ ИНТЕРФЕЙС ОТ ПРИЛОЖЕНИЯ hxxps://forum.aspnetboilerplate.com/viewtopic.php?f=2&t=3301

Очень похожая проблема (но без решения): hxxps://stackoverflow.com/questions/43747413/sending-cookie-cross-domain-with-cors-using-jquery-hosted-with-mvc-troubleshoo

Я также безуспешно пытался реализовать свой собственный WebClient на уровне .Web и предоставить файл cookie для последующих вызовов AJAX. Как лучше всего разрешить вызов AJAX для аутентификации в браузере?

P.S. это моя конфигурация запуска OWIN для аутентификации:

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Active,
            CookieHttpOnly = false,
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            LogoutPath = new PathString("/Account/Logout"),
            Provider = new CookieAuthenticationProvider
            {
                OnApplyRedirect = ctx =>
                {
                    if (!IsAjaxRequest(ctx.Request))
                    {
                        ctx.Response.Redirect(ctx.RedirectUri);
                    }
                }
            }
        }); 

Буду очень благодарен за любые ответы.


person Mantas Kareiva    schedule 31.05.2017    source источник
comment
Аутентификация на основе файлов cookie не работает с несколькими источниками, поскольку файлы cookie всегда привязаны к домену, независимо от ваших настроек CORS.   -  person Chris Pratt    schedule 31.05.2017
comment
Я так и думал :-( Спасибо за ответ.   -  person Mantas Kareiva    schedule 31.05.2017


Ответы (2)


Следуйте инструкциям здесь:

Включение запросов между источниками в ASP.NET Web API 2

https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Глобальное включение CORS Описанный выше метод также можно использовать для включения через API без аннотирования каждого контроллера:

public static void Register(HttpConfiguration config)
{
    var corsAttr = new EnableCorsAttribute("http://example.com", "*", "*");
    config.EnableCors(corsAttr);
}
person Alper Ebicoglu    schedule 28.06.2017

Я думаю, что проблема здесь в том, что файлы cookie не отправляются в браузер. Чтобы решить эту проблему, вам нужно сначала добавить следующий заголовок, чтобы указать браузеру предоставить ответ на ваш JS-код внешнего интерфейса.

<add name="Access-Control-Allow-Credentials" value="true" />

Затем при входе в JS-код вам нужно использовать

XMLHttpRequest.withCredentials

для включения межсайтовых запросов с использованием файлов cookie. Вы можете сделать что-то вроде:

$.ajax({
        url: "http://internallyAccesibleServer/Account/Login",
        type: "POST",
        contentType: "application/json",
        data: JSON.stringify({
            tenancyName: $("#TenancyName").val(),
            usernameOrEmailAddress: $("#EmailAddressInput").val(),
            password: $("#PasswordInput").val(),
            rememberMe: false
        }),
        xhrFields: {
            withCredentials: true
        }

О переадресации. Согласно документации ABP, если свойство targetUrl равно установить на ответ, то он перенаправляет на него.

person Thibault Nestor    schedule 18.04.2019