angular - 如何在 Angular2 rc3 路由中处理来自 oauth 重定向 url 的哈希片段

标签 angular oauth-2.0 angular2-routing access-token angular2-router3

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

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

在以前的 Angular1 应用程序中 ui-router能够在以下 route 使用:

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

这可以毫无问题地接受发回的重定向 url,然后将所有内容传递给 LoginController 以处理前端的其余身份验证/ token 业务。

然而,这个应用程序是 Angular2 和 Typescript,路由器查询参数似乎不太灵活,我在实现类似的解决方案时遇到了麻烦。我一直在基于 this section在文档中,但所有示例都在构建其他内容,例如 /heroes在进入查询参数的复杂部分之前,例如 /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 来处理它们的身份验证,但无论我如何深入研究文档,我似乎都找不到它。非常感谢任何有关如何实现此建议的建议。

最佳答案

我最终找到了一个解决方案,它使用首选的 PathLocationStrategy,但也在散列片段被删除后的 url 部分之前从 oauth 重定向 uri 中提取 token (来自最终答案 here,它是从以下 blog post 中的 QueryParams 和 Fragment 部分。

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

{
  path: 'login',
  component: LoginComponent
}

这会捕获重定向 url,但会丢弃散列片段之后的所有内容,从而删除我需要的 token 。为了防止它丢弃散列片段之后的所有内容,我将以下代码添加到我的 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);
});

您选择如何处理 token 完全取决于您(我有一个 TokenService,其中包含从 localStorage 设置、检索和清除它的方法),但这是您访问散列片段之后的 url 部分的方式。如果有人有更好的解决方案,请随时在此处更新/发布。

更新: 对上述登录组件代码进行小幅更新,以处理 Angular v4.2.0 中的“片段可能为空” typescript 错误,并在 tsconfig.json 中将 strictNullChecks 设置为 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 运算符已成为可管道化的,这意味着您必须在 Observablepipe 方法中传递它> 如下所示:

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

关于angular - 如何在 Angular2 rc3 路由中处理来自 oauth 重定向 url 的哈希片段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38255939/

相关文章:

javascript - 普通 Javascript 在 Angular CLI 组件中不起作用

angular - 我们如何将 Fine-uploader 与 Angular 5 一起使用?

Django OAuth 工具包设置问题

facebook-graph-api - Golang oauth 2 facebook 错误代码 2500(无法指定空标识符)

angular - 从另一个模块访问路由参数

angular - 当数据集更改时, ionic 虚拟滚动列表元素总是闪烁

javascript - 调用从 Angular 6 下载 pdf 的 Spring boot api 给出错误无法解析响应

swift - 列表需要 3 个元素,但我不知道第三个元素从哪里来

加载第一个子路由后,Angular2 路由不起作用

angular - 如何在 Angular 2 中重新加载相同 URL 的组件?