如何在 Angular2 rc3 路由中处理来自 oauth 重定向 url 的哈希片段 [英] How to handle hash fragments from oauth redirect urls in Angular2 rc3 routing

查看:25
本文介绍了如何在 Angular2 rc3 路由中处理来自 oauth 重定向 url 的哈希片段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种方法来处理设置 Angular2 Typescript 路由(使用 3.0.0-alpha.8 路由器),该路由将处理以哈希片段开头的路由.

I'm trying to find a way to handle setting up an Angular2 Typescript route (using the 3.0.0-alpha.8 router) that will handle routes that begin with hash fragments.

我正在开发的应用程序通过带有 oauth2 的 rails 后端处理所有外部登录(我无法控制的事情).将用户重定向到外部登录页面工作正常,但是当重定向 url 时,总是发送某种形式的 http://localhost:4200#access_token=TOKEN(其中 TOKEN 是一系列数字和字母)返回但我不知道如何设置可以处理 # 符号的路由,以便我可以捕获它并重定向到适当的组件.

The app I'm working on handles all login externally (something I have no control over) through a rails backend with oauth2. Redirecting users to the external login page works fine but when the redirect url, always some form of http://localhost:4200#access_token=TOKEN (where TOKEN is a series of numbers and letters) is sent back but I can't figure out how to set up a route that can handle the # sign so I can catch it and redirect to the appropriate component.

在之前的 Angular1 应用程序中,ui-router 能够在以下路径中使用:

In a previous Angular1 app the ui-router was able to use in a route of:

.state('accessToken', {
  url: '/access_token=:token',
  controller: 'LoginController',
  params: { token: null }
})

这在接受发回的重定向 url 时没有问题,然后将所有内容传递给 LoginController 以处理前端的其余身份验证/令牌业务.

and this had no problem accepting the redirect url that was sent back and would then pass everything over to the LoginController to handle the rest of the authentication/token business on the front end.

然而,这个应用程序是 Angular2 和 Typescript,路由器查询参数似乎不太灵活,我在实施类似的解决方案时遇到了麻烦.我一直在基于本节 在文档中,但所有示例都在构建其他内容,例如 /heroes,然后再进入查询参数的复杂部分,例如 /heroes/:id.我也搜索了 stackoverflow,但找不到任何适用于 Angular2 和 Typescript 以及当前路由器的内容.

This app however is Angular2 and Typescript and the router query params seem way less flexible and I'm having trouble implementing a similar solution. I've been going based on this section in the docs but all of the examples are building of something else, ex /heroes before getting to the complicated part of the query params, ex /heroes/:id. I searched through stackoverflow as well and wasn't able to find anything that worked with Angular2 and Typescript and the current router.

这是我目前的(非工作)解决方案:

This is my current (non working) solution:

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 的格式,而且我无法提出一个解决方案来处理它以哈希片段而不是 / 然后是我的查询参数.我能找到的所有带有复杂符号或字符的路由示例都以 / 开头.

If I take the redirect url that is sent back and modify it (purely for testing purposes) to something like http://localhost:4200/access_token=TOKEN it works fine. Unfortunately I don't actually have control over the format of the redirect url in real life, and I am unable to come up with a solution that can handle the fact that it begins with a hash fragment rather than a / and then my query params. All of the examples of routing with complicated symbols or characters that I can find begin with a /.

我尝试将上面的解决方案修改为 :access_token,但没有用,并将其列为基本路由下的子路由,如下所示:

I tried modifying my solution above to be :access_token, which did not work, as well as listing it as a child route under the base route like so:

{
  path: '',
  component: HomeComponent,
  terminal: true,
  children: [
    { path: 'access_token',  component: TestComponent },
  ]
}

导致以下控制台错误:platform-b​​rowser.umd.js:2312 例外:错误:未捕获(承诺):错误:无法匹配任何路由:''

which resulted in the following console error: platform-browser.umd.js:2312 EXCEPTION: Error: Uncaught (in promise): Error: Cannot match any routes: ''

我觉得绝对必须有一个干净的解决方案,特别是因为有这么多 API 通过像这样的重定向 url 来处理他们的身份验证,但无论我翻阅了多少文档,我似乎都找不到它.任何关于如何实现这一点的建议将不胜感激.

I feel like there absolutely has to be a clean solution to this, especially since so many APIs handle their authentication through a redirect url like this but no matter how much I dig through the docs I can't seem to find it. Any advice on how to implement this would be much appreciated.

推荐答案

我最终找到了一个解决方案,该解决方案使用首选的 PathLocationStrategy 并且在哈希之后的 url 部分之前从 oauth 重定向 uri 中提取令牌片段被删除(来自最终答案 here,这是从 QueryParams 和 Fragment 部分中提取的以下博文).

I was eventually able to find a solution that uses the preferred PathLocationStrategy but also pulls the token out of the oauth redirect uri before the part of the url after the hash fragment is dropped (from the final answer here which is pulled from the QueryParams and Fragment section in the following blog post).

本质上,我在使用 doorkeeper/oauth2 注册我的应用程序时将重定向 url 更新为 http://localhost:4200/login/(这使包含令牌的重定向 url 看起来像 http://localhost:4200/login/#access_token=TOKEN)并添加以下路由:

Essentially I updated the redirect url when registering my application with doorkeeper/oauth2 to be http://localhost:4200/login/ (which leads the redirect url containing the token to look like http://localhost:4200/login/#access_token=TOKEN) and added the following route:

{
  path: 'login',
  component: LoginComponent
}

这会捕获重定向 url,但会删除哈希片段之后的所有内容,删除我需要的令牌.为了防止它在哈希片段之后丢弃所有内容,我将以下代码添加到我的 LoginComponent 的构造函数中:

This catches the redirect url but drops everything after the hash fragment, removing the token I needed. To prevent it from dropping everything after the hash fragment I added the following code to the constructor of my 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 部分的方式.如果有人有更好的解决方案,请随时在此处更新/发布.

How exactly you choose to handle the token is up to you (I have a TokenService with methods to set, retrieve, and clear it from localStorage) but this is how you access the portion of the url after the hash fragment. Feel free to update/post here if anyone has a better solution.

更新:对上述登录组件代码的小更新以处理 Angular v4.2.0 & 中的片段可能为空"打字稿错误tsconfig.json 中的 strictNullChecks 设置为 true 以防有人需要它.功能是一样的:

UPDATE: Small update to the above login component code to deal with 'fragment is possibly null' typescript errors in Angular v4.2.0 & strictNullChecks set to true in the tsconfig.json in case anyone needs it. Functionality is the same:

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 操作符已经成为可管道化的,这意味着你必须在 Observablepipe 方法中传递它> 如下图所示:


Note: Since RxJS 6, the map operator has been made pipeable which means that you have to pass it in the pipe method of Observable as seen below:

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);
    }

这篇关于如何在 Angular2 rc3 路由中处理来自 oauth 重定向 url 的哈希片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆