Я пришел из мира Asp.Net MVC, где пользователи, пытающиеся получить доступ к странице, которую они не авторизовали, автоматически перенаправляются на страницу входа.
Я пытаюсь воспроизвести это поведение на Angular. Я наткнулся на декоратор @CanActivate, но это приводит к тому, что компонент вообще не отображается, нет перенаправления.
У меня следующий вопрос:
- Предоставляет ли Angular способ добиться такого поведения?
- Если да, то как? Это хорошая практика?
- Если нет, что было бы лучше всего для обработки авторизации пользователей в Angular?
Ответы:
Обновление: я опубликовал полный скелет проекта Angular 2 с интеграцией OAuth2 на Github, который показывает указанную ниже директиву в действии.
Один из способов сделать это - использовать расширение
directive
. В отличие от Angular 2components
, которые в основном представляют собой новые HTML-теги (со связанным кодом), которые вы вставляете на свою страницу, атрибутивная директива - это атрибут, который вы помещаете в тег, который вызывает определенное поведение. Документы здесь .Наличие вашего настраиваемого атрибута приводит к тому, что что-то происходит с компонентом (или элементом HTML), в который вы поместили директиву. Рассмотрим эту директиву, которую я использую для моего текущего приложения Angular2 / OAuth2:
Это использует службу аутентификации, которую я написал, чтобы определить, вошел ли уже пользователь в систему, а также подписывается на событие аутентификации, чтобы оно могло выгнать пользователя, если он или она выйдет из системы или истечет время ожидания.
Вы могли бы сделать то же самое. Вы бы создали такую директиву, как моя, которая проверяет наличие необходимого файла cookie или другой информации о состоянии, которая указывает, что пользователь аутентифицирован. Если у них нет тех флагов, которые вы ищете, перенаправьте пользователя на свою главную общедоступную страницу (как я) или на ваш сервер OAuth2 (или что-то еще). Вы бы поместили этот атрибут директивы на любой компонент, который необходимо защитить. В этом случае он может называться
protected
как в директиве, которую я вставил выше.Затем вы захотите перейти / перенаправить пользователя в представление входа в ваше приложение и обработать там аутентификацию. Вам придется изменить текущий маршрут на тот, который вы хотите сделать. Итак, в этом случае вы должны использовать внедрение зависимостей, чтобы получить объект Router в функции вашей директивы,
constructor()
а затем использовать этотnavigate()
метод для отправки пользователя на страницу входа в систему (как в моем примере выше).Это предполагает, что у вас есть серия маршрутов где-то, управляющих
<router-outlet>
тегом, который выглядит примерно так, например:Если вместо этого вам нужно перенаправить пользователя на внешний URL-адрес, такой как ваш сервер OAuth2, тогда ваша директива будет делать что-то вроде следующего:
источник
Вот обновленный пример с использованием Angular 4 (также совместим с Angular 5-8)
Маршруты с домашним маршрутом, защищенным AuthGuard
AuthGuard перенаправляет на страницу входа, если пользователь не вошел в систему
Обновлено для передачи исходного URL-адреса в параметрах запроса на страницу входа
Полный пример и рабочую демонстрацию вы можете посмотреть в этом посте.
источник
currentUser
в,localStorage
все равно будет иметь доступ к защищенному маршруту? например.localStorage.setItem('currentUser', 'dddddd')
?Использование с финальным маршрутизатором
С введением нового маршрутизатора стало проще охранять маршруты. Вы должны определить охранник, который действует как служба, и добавить его в маршрут.
Теперь передайте в
LoggedInGuard
маршрут и также добавьте его вproviders
массив модуля.Объявление модуля:
Подробное сообщение в блоге о том, как это работает с финальной версией: https://medium.com/@blacksonic86/angular-2-authentication-revisited-611bf7373bf9
Использование устаревшего маршрутизатора
Более надежным решением является расширение
RouterOutlet
и при активации проверки маршрута, если пользователь вошел в систему. Таким образом, вам не нужно копировать и вставлять свою директиву в каждый компонент. Кроме того, перенаправление на основе подкомпонента может ввести в заблуждение.Это
UserService
означает место, где находится ваша бизнес-логика, независимо от того, вошел ли пользователь в систему или нет. Вы можете легко добавить его с помощью DI в конструкторе.Когда пользователь переходит на новый URL-адрес на вашем веб-сайте, вызывается метод активации с текущей инструкцией. Из него вы можете получить URL-адрес и решить, разрешено это или нет. Если не просто перенаправить на страницу входа.
И последнее, что осталось сделать, чтобы он заработал, - это передать его нашему основному компоненту вместо встроенного.
Это решение нельзя использовать с
@CanActive
декоратором жизненного цикла, потому что, если переданная ему функция разрешает false, метод активацииRouterOutlet
не будет вызываться.Также написал подробный пост в блоге об этом: https://medium.com/@blacksonic86/authentication-in-angular-2-958052c64492
источник
Failed to lint <classname>.router-outlet.ts[15,28]. In the constructor of class "LoggedInRouterOutlet", the parameter "nameAttr" uses the @Attribute decorator, which is considered as a bad practice. Please, consider construction of type "@Input() nameAttr: string".
Не удалось понять, что изменить в конструкторе ("_parentRounter"), чтобы избавиться от этого сообщения. Есть предположения?_parentRouter: Router, @Input() nameAttr: string,
и tslint больше не вызывает ошибку. Также заменен импорт «Атрибутов» на «Ввод» из ядра angular. Надеюсь это поможет.Пожалуйста, не перекрывайте выход маршрутизатора! Это кошмар с последней версией роутера (3.0 beta).
Вместо этого используйте интерфейсы CanActivate и CanDeactivate и установите класс как canActivate / canDeactivate в определении маршрута.
Как это:
Класс:
См. Также: https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard.
источник
Следуя замечательным ответам выше, я также хотел бы
CanActivateChild
: охранять дочерние маршруты. Его можно использовать для добавленияguard
дочерним маршрутам, полезным для таких случаев, как ACL.Это выглядит так
Это взято из https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard
источник
Обратитесь к этому коду, файлу auth.ts
источник
1. Create a guard as seen below. 2. Install ngx-cookie-service to get cookies returned by external SSO. 3. Create ssoPath in environment.ts (SSO Login redirection). 4. Get the state.url and use encodeURIComponent.
источник