Angular2: условное перенаправление на другой маршрут при выходе из системы

Я немного борюсь с конкретным вариантом использования Angular2 и маршрутизатора.

Допустим, у нас есть 3 маршрута. Главная, список и профиль.

«Профиль» — это защищенный маршрут: пользователь должен пройти аутентификацию, чтобы получить доступ к этому маршруту.

Если пользователь находится на странице «Профиль» и выходит из системы, я хочу иметь возможность определить, что ему больше не разрешено находиться на текущей странице, и перенаправить его на «Домашнюю» страницу.

Однако, если он находится на странице «Список» и выходит из системы, я не хочу ничего делать (пользователю разрешено оставаться здесь, поскольку это не охраняемый маршрут).

Кто-нибудь знает, как я могу этого добиться, предполагая, что у меня много маршрутов, и я хочу избежать включения этой логики «разрешено пользователю» в каждый компонент?


person Jonathan Trang    schedule 17.12.2016    source источник


Ответы (2)


Сводка

В моем случае мне нравится предоставлять пользователю доступ к защищенным маршрутам, проверяя валидацию токена, который я сохраняю в локальном хранилище. Поэтому, если я выхожу из них, я удаляю токен вместе со всеми данными, которые у меня есть в настоящее время в локальном хранилище. Вы можете использовать эту функцию на каждом маршруте.

  public logout() {
    localStorage.removeItem('profile');
    localStorage.removeItem('access_token');
    this.userProfile = undefined;
    this.router.navigateByUrl('/home');
  };

Я создаю сервис для аутентификации. Вы можете создать две разные службы или две разные функции. На самом деле у вас есть много вариантов. Вот один из вариантов.

Решение

Чтобы выйти из системы и перенаправить,

  public logout() {
    localStorage.removeItem('profile');
    localStorage.removeItem('access_token');
    this.userProfile = undefined;
    this.router.navigateByUrl('/home');
  };

Вы можете использовать эту функцию в каждом из ваших компонентов. Или страницы. В основном перенаправляйте маршрут, если пользователь находится на странице профиля. но если пользователь не находится на странице или маршруте, который необходимо перенаправить, удалите

this.router.navigateByUrl('/home');

Из функции, чтобы пользователь не перенаправлялся.

Таким образом, вы можете иметь два сервиса

    public.service.ts
    @Injectable()
export class Public {
     public logout() {
        localStorage.removeItem('profile');
        localStorage.removeItem('access_token');
        this.userProfile = undefined;
      };

Затем на ваших страницах, на которых вы хотите выйти из системы, но оставить их на той же странице, используйте эту услугу.

export class SomeComponent {
       constructor( private router: Router, private public: Public  ) { }
}

Поэтому, когда вы используете функцию выхода из системы, она не будет перенаправляться.

Затем, чтобы перенаправить, когда пользователь выходит из системы, добавьте эту службу следующим образом:

       secure.service.ts
    @Injectable()
export class Secure {
     public logout() {
        localStorage.removeItem('profile');
        localStorage.removeItem('access_token');
        this.userProfile = undefined;
        this.router.navigateByUrl('/home');
      };

И, конечно же, любой компонент, который вы включаете в службу, также вызывается правильным logout function в вашем html вот так,

<a class="myClass" href="#"(click)="public.logout()">Logout</a>

or

<a class="myClass" href="#" (click)="secure.logout()">Logout</a>
person wuno    schedule 17.12.2016
comment
Без проблем. Это имело смысл? и помочь? - person wuno; 19.12.2016
comment
На самом деле я придумал что-то похожее, но хотел избежать включения логики в каждый компонент, что может быть немного громоздким, если у вас их много. Думаю, другого выхода нет :/ - person Jonathan Trang; 19.12.2016
comment
Вам не нужно помещать его в каждый компонент. Вы можете сделать безопасный шаблон и общедоступный шаблон. Затем поместите кнопку выхода в шаблон. Затем включите страницы в шаблон. Таким образом, любая страница, которая должна быть в безопасном шаблоне, будет дочерней для secure.component.ts. Я ответил на многие вопросы, которые ищут подобную настройку. Я объясню, как это сделать здесь stackoverflow.com/a/41219564/2218253 - person wuno; 19.12.2016
comment
Если это отвечает на ваш вопрос, пожалуйста, примите мой ответ как правильный с галочкой рядом с моим ответом. Если нет, то, пожалуйста, дайте мне знать, что неясно, и я постараюсь объяснить, чтобы продолжать помогать вам. - person wuno; 19.12.2016
comment
Я понимаю ваш подход. Но, похоже, это работает только в том случае, если кнопка выхода находится в шаблоне компонента (защищенном или общедоступном). В моем случае ссылка для выхода находится в NavComponent, который является компонентом верхнего уровня и является общим для всех дочерних компонентов (защищенных или общедоступных). - person Jonathan Trang; 19.12.2016
comment
Да. ТАК, что я говорю, это создать два компонента навигации. Один для безопасного и один для публики. Затем сделайте все остальное потомками тех. Поэтому в основном измените компонент навигации на безопасный и общедоступный компонент. Затем вы можете добавить нижний колонтитул к каждому, если хотите, а затем просто заполнить тело любым содержимым, которое хотите. В зависимости от того, является ли это защищенной страницей или общедоступной страницей. - person wuno; 19.12.2016
comment
Привет Вуно. Извините за задержку, мне нужно было найти время, чтобы реализовать это должным образом. Ваше решение работает отлично, спасибо за вашу помощь и терпение! - person Jonathan Trang; 01.01.2017
comment
Без проблем! Дай мне знать если тебе нужно что-нибудь еще - person wuno; 01.01.2017
comment
Привет, wuno, я только что реализовал решение, подобное описанному вами, с помощью шаблонов, но теперь, когда я нахожусь на общедоступной странице (но вошел в систему с помощью защищенного шаблона) и нажимаю кнопку выхода из системы, я ожидаю, что он переключится на общедоступный шаблон, но, вероятно, потому, что URL-адрес не был изменен (потому что мне не нужно перенаправлять с общедоступной страницы). Я что-то упустил в вашем решении или мне нужно обновить / перезагрузить маршрутизатор? если да, то как? - person DiSol; 05.05.2017
comment
Я всегда обслуживаю публичные страницы на общедоступном шаблоне. и безопасные страницы на безопасных шаблонах. Поэтому, если вы показываете общедоступную страницу в защищенном шаблоне, кажется, что самым простым решением будет перенаправить кого-то обратно на общедоступную страницу. this.router.navigateByUrl('/public-page'); - person wuno; 05.05.2017
comment
Да, я понимаю, что перенаправление — это самое простое решение, но это неправильно с точки зрения UX, потому что я обновляю страницу, когда это не нужно... На самом деле это была настоящая причина, по которой я применил этот подход. :) - person DiSol; 05.05.2017
comment
Единственный способ, который я могу придумать, - это обновить все компоненты на странице, когда кто-то выходит из системы. Поэтому все, что нужно изменить, когда кто-то выходит из системы, вам придется использовать наблюдаемое для обновления. Таким образом, в основном он будет ждать и наблюдать за определенным действием, а затем, когда он будет выполнять наблюдаемые обновления на основе новой информации. - person wuno; 05.05.2017
comment
Что означает обновить все компоненты на странице? Как я могу обновить компонент? - person DiSol; 05.05.2017
comment
Теперь я действительно понял, что ваше решение идеально и работает как положено — я обнаружил, что не обновлял какую-то переменную, отвечающую за переключение между кнопками. Спасибо за помощь! - person DiSol; 05.05.2017
comment
Без проблем. Рад, что смог помочь! - person wuno; 05.05.2017

Этого можно достичь с помощью одного компонента (меню), который обслуживает все маршруты, общедоступные и частные, где частные маршруты становятся видимыми только при входе в систему.

Этот же компонент также включает кнопку выхода, видимую только при входе в систему. Обработчик для этого выходит и определяет, требуется ли вход для текущего маршрута. Если да, перенаправить на домашнюю страницу, если нет, ничего не делать.

Защищенные частные маршруты, вероятно, будут определены в app.module с определением canActivate, поэтому для этих путей требуется вход.

app.module.ts

const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'sign-in', component: SignInComponent },
  { path: 'private', loadChildren: './private/private.module#PrivateModule', 
canActivate: [LoginRouteGuardService] }
];

menu.component.ts

signOut() {
  // your sign out method
  // then check if redirect necessary
  if (this.router.url.includes('/private/')) {
    this.router.navigateByUrl('/');
  }
}

Вариант вышеизложенного представлен здесь: https://stackblitz.com/edit/free-vote-redirect-on-sign-out

person Alex Cooper    schedule 31.10.2018