Событие NavigationCancel, созданное для действительных охранников в Angular 6 - PullRequest
0 голосов
/ 10 октября 2018

У меня проблемы с маршрутизатором Angular во время перехода к указанному состоянию.

Я пытался использовать настраиваемую защиту с функциями canLoad() и canActivate(), возвращающими логические значения как trueбез всякой удачи.

Angular документы заявляет следующее:

NavigationCancel: Событие, инициируемое при отмене навигации.Это связано с тем, что Route Guard возвращает false во время навигации.

Поскольку я больше не получаю отладочную информацию от трассировки маршрутизатора (причина не указана), я вынужден проверить здесь, есть ли исправлениеили, если это существующая ошибка.Я также ценю любую информацию, касающуюся других средств отладки маршрутизатора в Angular 6.

Вывод на консоль

console output

Я создал небольшой проект в здесь .Проект требует доступа к провайдеру, я использую предоставленный провайдер OpenID Connect, указанный в репозитории angular-oauth2-oidc.Пароль / имя пользователя max / geheim.

Как воспроизвести ошибку

  1. Клонировать репо и обслуживать сайт на локальном хосте: 4200
  2. Перейти к localhost: 4200 / oversikt / index
  3. Войти с max / geheim как имя пользователя / пароль
  4. Считать консоль

ОБНОВЛЕНИЕ Iподозреваю, что это как-то связано с переходом на children: [] маршрутов.

1 Ответ

0 голосов
/ 20 октября 2018

Я сделал небольшую отладку в вашем коде и обнаружил, что это не из-за ссылок, аутентификации, декларации навигации или конфигурации модуля или из-за того, что маршрутизатор не работает в AG6 , но это потому, чтоиз ..... OAuth lib вы используете .

Но позвольте мне объяснить.Я обнаружил, что происходит следующий сценарий:

  1. Вы авторизуетесь и вы перенаправлены обратно на страницу
  2. Вы возвращаетесь в приложение со ссылкой типа / # YOUR AUT TOKEN
  3. Запланирована первая навигация (id 1)
  4. Результатом навигации является перенаправление на подстраницу / превышение
  5. Всплывающая навигация 2 (перенаправление)
  6. Маршрутизатор выполняет все операции асинхронно- они сериализованы, но все еще используют RxJS - поэтому фактическая обработка задерживается - она ​​передала текущий идентификатор навигации в качестве аргумента (это важно)
  7. Некоторые слушатели и другие подписки запускаются, а также вещи из вашей OAUTH-библиотеки, которыевы используете
  8. Он (lib) обнаруживает, что у вас есть токен в вашем URL-адресе, и УДАЛЯЕТ ЕГО
  9. , который запускает другое перенаправление - идентификатор маршрутизации УВЕЛИЧИЛСЯ ПРАВО К 3
  10. Сейчаснавигация 2 продолжается и в какой-то момент (помните, что JS является однопоточным), он проверяет (хорошо, что это делает много), если идентификатор навигации с началаНавигация навигации изменилась или осталась прежней.
  11. Так как она имеет изменения - идентификатор 2 был передан во время расписания, а текущая навигация равна 3, один false распространяется по всем каналам и подписке в маршрутизаторе.
  12. Наличие boolean (даже не false, а bool) в качестве значения в pipe приводит к безусловной навигации CANCEL.

Я добавлю некоторые ссылки на код.Но в целом так и происходит.Ваша библиотека oauth изменяет URL во время навигации, что приводит к его отмене.Охранники не имеют ничего общего с этим прямым путем.

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

Вот (не все) связанный код:

Изменение библиотеки OAuth

   if (!this.oidc) {
            this.eventsSubject.next(new OAuthSuccessEvent('token_received'));
            if (this.clearHashAfterLogin && !options.preventClearHashAfterLogin) {
                location.hash = '';
            }
            return Promise.resolve();
        }

Запуск по изменению URL:

 Router.prototype.setUpLocationChangeListener = function () {
        var _this = this;
        // Don't need to use Zone.wrap any more, because zone.js
        // already patch onPopState, so location change callback will
        // run into ngZone
        if (!this.locationSubscription) {
            this.locationSubscription = this.location.subscribe(function (change) {
                var rawUrlTree = _this.parseUrl(change['url']);
                var source = change['type'] === 'popstate' ? 'popstate' : 'hashchange';
                if(this.rou)
                var state = change.state && change.state.navigationId ?
                    { navigationId: change.state.navigationId } :
                    null;
                setTimeout(function () { console.error("FROM LOCATION SUB");_this.scheduleNavigation(rawUrlTree, source, state, { replaceUrl: true }); }, 0);
            });
        }
    };

Изменение идентификатора Nav - происходит сразу:

   var id = ++this.navigationId;
    console.error("ANOTHER SCHEDULED LOL LOL LOL!!!");
    this.navigations.next({ id: id, source: source, state: state, rawUrl: rawUrl, extras: extras, resolve: resolve, reject: reject, promise: promise });
    // Make sure that the error is propagated even though `processNavigations` catch
    // handler does not rethrow
    return promise.catch(function (e) { return Promise.reject(e); });

Это то, что передается маршрутизатору для запуска «асинхронной» маршрутизации - id - это идентификатор Nav (увеличенный ранее)

 Router.prototype.runNavigate = function (url, rawUrl, skipLocationChange, replaceUrl, id, precreatedState) {

Эта проверка (она в runNav) завершается неудачно, так как сначала при изменении идентификатора, поэтому 2! == 3 - FALSE возвращается в канал

var preactivationCheckGuards$ = preactivationSetup$.pipe(mergeMap(function (p) {
            if (typeof p === 'boolean' || _this.navigationId !== id) //NAVIGATION ID CHANGES HERE!
            {
              console.warn("PREACTIVATE GUARD CHECK ");
              console.log(p);
              // debugger;
              return of(false);
            }

есть еще несколько подписок в chaingвсе они имеют некоторые конвейерные сопоставления и т. д., а также проверку известных условий.

 var preactivationResolveData$ = preactivationCheckGuards$.pipe(mergeMap(function (p) {
                if (typeof p === 'boolean' || _this.navigationId !== id)
                    return of(false);

Обратите внимание, что это то, что я написал ранее, что если вы получите ЛЮБОЙ логический элемент здесь, false выдвигается вперед.Так как false здесь уже есть, потому что проверка не удалась в предыдущей карте канала ....

Наконец, в конце цепочки

    if (typeof p === 'boolean' || !p.shouldActivate || id !== _this.navigationId || !p.state) {
      // debugger;
        navigationIsSuccessful = false;
        return;
    }

флаг результата установлен в false, и это приводит к результатамв

 .then(function () {
        if (navigationIsSuccessful) {
            _this.navigated = true;
            _this.lastSuccessfulId = id;
            _this.events
                .next(new NavigationEnd(id, _this.serializeUrl(url), _this.serializeUrl(_this.currentUrlTree)));
            resolvePromise(true);
        }
        else {
            _this.resetUrlToCurrentUrlTree();
            _this.events
                .next(new NavigationCancel(id, _this.serializeUrl(url), ''));
            resolvePromise(false);
        }

NavigationCancel без какого-либо сообщения (последний параметр - это сообщение - строка emtpy здесь), которое вы хорошо знаете:).

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

как для документов

NavigationCancel: событие, инициированное, когда навигация отменяется.Это происходит из-за того, что Route Guard возвращает false во время навигации.

ну, они забыли упомянуть, что внутренне маршрутизатор может отменить навигацию, если нарастает очередь навигации:)

Cheers!

...