Как обрабатывать хеш-фрагменты с oauth перенаправлять URL-адреса в Angular2 rc3 routing
Я пытаюсь найти способ справиться с настройкой маршрута Angular2 Typescript (используя маршрутизатор 3.0.0-alpha.8), который будет обрабатывать маршруты, начинающиеся с хеш-фрагментов.
Приложение, над которым я работаю, обрабатывает все входы в систему извне (то, что я не могу контролировать) через бэкэнд рельсов с oauth2. Перенаправление пользователей на внешнюю страницу входа в систему работает нормально, но когда URL-адрес перенаправления, всегда http://localhost:4200#access_token=TOKEN
форма http://localhost:4200#access_token=TOKEN
(где TOKEN - серия цифр и букв), но я не могу понять Как настроить маршрут, который может обрабатывать знак #
чтобы я мог поймать его и перенаправить на соответствующий компонент.
В предыдущем приложении Angular1 ui-router
мог использовать маршрут:
.state('accessToken', {
url: '/access_token=:token',
controller: 'LoginController',
params: { token: null }
})
и у него не было проблем с принятием URL перенаправления, который был отправлен обратно, и затем он передавал бы все на LoginController для обработки остальной части бизнеса аутентификации/токена на внешнем интерфейсе.
Это приложение, однако, Angular2 и Typescript, и параметры запроса маршрутизатора кажутся менее гибкими, и у меня возникают проблемы при реализации аналогичного решения. Я опирался на этот раздел в документации, но все примеры строят что-то еще, например, ex /heroes
прежде чем перейти к сложной части параметров запроса, ex /heroes/:id
. Я также искал через stackoverflow и не смог найти ничего, что работало бы с Angular2 и Typescript и текущим маршрутизатором.
Это мое текущее (нерабочее) решение:
import { provideRouter, RouterConfig } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { TestComponent } from './components/test/test.component';
export const appRoutes: RouterConfig = [
{
path: '',
component: HomeComponent,
terminal: true
},
{
path: 'access_token',
component: TestComponent
}
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(appRoutes)
];
Если я возьму перенаправленный URL-адрес, который был отправлен обратно, и изменил его (исключительно для целей тестирования) на что-то вроде http://localhost:4200/access_token=TOKEN
он будет работать нормально. К сожалению, на самом деле я не могу контролировать формат URL-адреса перенаправления в реальной жизни, и я не могу найти решение, которое может справиться с тем фактом, что оно начинается с хеш-фрагмента, а не с /
а затем с параметрами моего запроса, Все примеры маршрутизации со сложными символами или символами, которые я могу найти, начинаются с /
.
Я попытался изменить свое решение выше :access_token
, который не работал, а также перечислить его как дочерний маршрут под базовым маршрутом следующим образом:
{
path: '',
component: HomeComponent,
terminal: true,
children: [
{ path: 'access_token', component: TestComponent },
]
}
что привело к следующей ошибке консоли: platform-browser.umd.js:2312 EXCEPTION: Error: Uncaught (in promise): Error: Cannot match any routes: ''
Я чувствую, что должно быть абсолютно чистое решение, особенно потому, что очень много API обрабатывают свою аутентификацию через URL-адрес перенаправления, как это, но независимо от того, сколько я копаю в документах, я не могу найти его. Любые советы о том, как реализовать это, будут высоко оценены.
Ответы
Ответ 1
Я был в конечном итоге удалось найти решение, которое использует предпочтительный PathLocationStrategy, но и тянет фишку из OAuth перенаправления URI до части URL после того, как фрагмент хэш отбрасывается (от окончательного ответа здесь, который вытягивается из QueryParams и фрагмента раздел в следующем сообщении в блоге).
По сути, я обновил URL-адрес перенаправления при регистрации приложения с помощью doorkeeper/oauth2, чтобы он был http://localhost: 4200/login/ (что приводит к тому, что URL-адрес перенаправления, содержащий токен, выглядит как http://localhost:4200/login/#access_token=TOKEN
) и добавил следующий маршрут:
{
path: 'login',
component: LoginComponent
}
Это перехватывает URL перенаправления, но удаляет все после фрагмента хеша, удаляя нужный мне токен. Чтобы предотвратить сброс всего после фрагмента хеша, я добавил следующий код в конструктор моего LoginComponent
:
constructor(private activatedRoute: ActivatedRoute,
private router: Router,
private tokenService: TokenService) {
// Pulls token from url before the hash fragment is removed
const routeFragment: Observable<string> = activatedRoute.fragment;
routeFragment.subscribe(fragment => {
let token: string = fragment.match(/^(.*?)&/)[1].replace('access_token=', '');
this.tokenService.setToken(token);
});
}
Как именно вы решите обращаться с токеном, зависит от вас (у меня есть TokenService с методами для установки, извлечения и очистки его из localStorage), но именно так вы получаете доступ к части URL после фрагмента хеша. Не стесняйтесь обновлять/публиковать здесь, если у кого-то есть лучшее решение.
ОБНОВЛЕНИЕ: Небольшое обновление вышеприведенного кода компонента входа в систему, чтобы иметь дело с ошибками машинописания "фрагмент - возможно, ноль" в Angular v4.2.0 и в качестве значения trueNullChecks в tsconfig.json установлено значение true, если кому-то это нужно. Функциональность одинакова:
let routeFragment = this.activatedRoute.fragment.map(fragment => fragment);
routeFragment.subscribe(fragment => {
let f = fragment.match(/^(.*?)&/);
if(f) {
let token: string = f[1].replace('access_token=', '');
this.tokenService.setToken(token);
}
Примечание: Так как RxJS 6, map
оператора было сделано pipeable, что означает, что вы должны передать его в pipe
методом Observable
, как показано ниже:
import { map } from 'rxjs/operators';
// ...
this.activatedRoute.fragment
.pipe(map(fragment => fragment))
.subscribe(fragment => {
let f = fragment.match(/^(.*?)&/);
if(f) {
let token: string = f[1].replace('access_token=', '');
this.tokenService.setToken(token);
}