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

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

问题描述

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



我正在使用的应用程序通过带有oauth2的rails后端处理所有外部登录(我无法控制)。将用户重定向到外部登录页面可以正常工作,但是当重定向URL时,总是使用 http:// localhost:4200#access_token = TOKEN 的某种形式(其中TOKEN是一系列数字和字母)发送回去,但我不知道如何设置可以处理标志的路线,因此我可以抓住它并将其重定向到适当的组件。



在以前的Angular1应用中, ui路由器可以在以下路径中使用:

  .state('accessToken',{
url:'/ access_token =:token',
控制器:' LoginController',
参数:{token:null}
})

和接受返回的重定向URL没问题,然后将所有内容传递给LoginController来处理前端的其余身份验证/令牌业务。



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



这是我目前(不起作用)的解决方案:

  import {ProvideRouter,RouterConfig}从'@ angular / router'; 

从 ./components/home/home.component导入{HomeComponent};
从 ./components/test/test.component导入{TestComponent};


导出const app路由:RouterConfig = [
{
路径:,
组件:HomeComponent,
终端:true
},
{
路径: access_token,
组件:TestComponent
}
];

导出常量APP_ROUTER_PROVIDERS = [
ProvideRouter(appRoutes)
];

如果我使用发送回的重定向URL并将其修改(纯粹出于测试目的)像 http:// localhost:4200 / access_token = TOKEN 一样可以正常工作。不幸的是,我实际上在现实生活中无法控制重定向URL的格式,并且我无法提出一种解决方案,该解决方案可以处理以下事实:它以散列片段开头,而不是 / 然后是我的查询参数。我可以找到的所有带有复杂符号或字符的路由示例均以 / 开头。



我尝试将上面的解决方案修改为:access_token ,但该方法无效,并列出了基本路线下的子路线,如下所示:

  {
path:'',
组件: HomeComponent,
终端:true,
子级:[
{路径: access_token,组件:TestComponent},
]
}

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



我觉得绝对必须干净解决此问题的方法,尤其是因为如此多的API通过这样的重定向URL处理身份验证,但是无论我在文档中挖掘了多少,我似乎都找不到它。

解决方案

我最终能够找到使用首选PathLocationStrategy的解决方案。而且还会在删除散列片段之后将Token从网址的一部分之前的oauth重定向uri中拉出(来自最终答案此处,该内容从以下

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



< pre class = lang-json prettyprint-override> {
路径: login,
组件:LoginComponent
}

这将捕获重定向URL,但是将所有内容都丢弃在散列片段之后,从而删除了我需要的令牌。为了防止它丢弃散列片段之后的所有内容,我在我的 LoginComponent 的构造函数中添加了以下代码:

 构造函数(私有激活路由:ActivatedRoute,
私有路由器:路由器,
私有tokenService:TokenService){

//在删除散列片段之前从网址中提取令牌

const routeFragment:Observable< string> = ActivateRoute.fragment;
routeFragment.subscribe(fragment => {
let令牌:string = fragment.match(/^(.*?)& amp; /)[1] .replace('access_token =','' );
this.tokenService.setToken(token);
});;

}



您如何选择处理令牌取决于您(我有一个TokenService,其中包含可从localStorage进行设置,检索和清除的方法),但这是您访问哈希片段之后的部分网址的方式。如果有人有更好的解决方案,请随时在此处更新/发布。



更新:
对上述登录组件代码进行小幅更新以应对碎片 Angular v4.2.0&中的 null打字稿错误。如果有人需要,则在tsconfig.json中将strictNullChecks设置为true。功能是一样的:

  let routeFragment = this.activatedRoute.fragment.map(fragment => ;片段); 

routeFragment.subscribe(fragment => {
let f = fragment.match(/^(.*?)& amp; /);
if(f){
let令牌:字符串= f [1] .replace('access_token =','');
this.tokenService.setToken(token);
}






注意:自RxJS 6起,地图运算符已变为可传递管道,这意味着您必须通过可观察管道方法传递它

  import {map} from'rxjs / operators'; 

// ...

this.activatedRoute.fragment
.pipe(map(fragment => fragment))
.subscribe(fragment => {
let f = fragment.match(/^(.*?)& amp; /);
if(f){
let令牌:string = f [1] .replace('access_token =' ,'');
this.tokenService.setToken(token);
}


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.

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.

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

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.

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

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 /.

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 },
  ]
}

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

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.

解决方案

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).

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
}

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

}

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.

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


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天全站免登陆