如何使用 HashLocationStrategy 和 Auth0 Lock 小部件进行用户登录
Posted
技术标签:
【中文标题】如何使用 HashLocationStrategy 和 Auth0 Lock 小部件进行用户登录【英文标题】:How to use the HashLocationStrategy with the Auth0 Lock widget for user login 【发布时间】:2017-01-31 04:18:53 【问题描述】:更新Auth0 login sample 以在app.module.ts
中使用HashLocationStrategy
后:
import LocationStrategy, HashLocationStrategy from '@angular/common';
// (...)
@NgModule(
providers: [
provide: LocationStrategy, useClass: HashLocationStrategy,
appRoutingProviders,
AUTH_PROVIDERS
],
//(...)
不再引发 Auth0 Lock authenticated
事件:
import Injectable from '@angular/core';
import tokenNotExpired from 'angular2-jwt';
// Avoid name not found warnings
declare var Auth0Lock: any;
@Injectable()
export class Auth0Service
// Configure Auth0
lock = new Auth0Lock('I21EAjbbpf...', '....au.auth0.com', );
constructor()
// Add callback for lock `authenticated` event
this.lock.on("authenticated", (authResult) =>
// Use the token in authResult to getProfile() and save it to localStorage
this.lock.getProfile(authResult.idToken, function(error, profile)
if (error)
// Handle error
return;
localStorage.setItem('id_token', authResult.idToken);
localStorage.setItem('profile', JSON.stringify(profile));
);
);
// (...)
【问题讨论】:
你遇到了什么错误? 【参考方案1】:您遇到此问题的原因是,Angular 2 路由器会在路由导航时自动清理 URL,导致 Auth0 Lock 永远看不到验证用户所需的数据。从 GitHub 来看,这种行为并不总是这样,但它是当前的。有关背景信息,请参阅 RC2 Router strips extra arguments from the path after matching a route 和 navigation should not preserve query params and fragment。
在执行登录时,Auth0 将请求您的浏览器导航到类似于此的 URL:
http://example.com/#access_token=RENH3twuqx&id_token=eyJ0.epcOidRwc.Qdx3ac&token_type=Bearer
此 URL 包含 Lock 识别用户已通过身份验证的所有必要信息,但是,前面提到的 Angular 路由器行为意味着在 Lock 有机会处理此信息之前,身份验证数据包含在 URL 片段中的 URL 被剥离,保留 URL 为 (http://example.com/#/
)。发生这种情况是因为您很可能已经配置了与任何 URL 匹配的包罗万象的路由。
假设您配置了以下路由:
const appRoutes: Routes = [
path: '', component: HomeComponent ,
path: '**', redirectTo: ''
];
免责声明:下面将显示的第一个解决方案是作为一种解决方法提供的,该解决方案被证明适用于 Angular 2.0.0、Angular 路由器 3.0.0 与 Lock 10.2 一起使用。从那以后,路由器和/或 Lock 似乎发生了一些变化,导致最初的解决方法失败了。我提供了第二种解决方法,它似乎适用于 Angular 2.4.1、Angular 路由器 3.4.1 和 Lock 10.7。 p>
解决方法 #1 - (angular/core@2.0.0, angular/router@3.0.0, lock@10.2)
尝试规避此默认行为的一种可能方法是执行以下步骤:
-
向处理身份验证回调请求的路由添加激活保护,以在当前 URL 似乎是登录结果时不允许激活路由(例如,包含
access_token
关键字在它的片段中。
在触发经过身份验证的事件后,强制导航到您想要的路线,以便应用程序识别登录。
您可以创建以下类:
import Injectable from '@angular/core';
import CanActivate from '@angular/router';
import Location from '@angular/common';
@Injectable()
export class AuthenticationCallbackActivateGuard implements CanActivate
constructor(private location: Location)
canActivate()
// You may want to make a more robust check here
return this.location.path(true).indexOf("access_token") === -1;
将其注册为您的家乡路线的守卫:
const appRoutes: Routes = [
path: '', component: HomeComponent, canActivate: [AuthenticationCallbackActivateGuard] ,
path: '**', redirectTo: ''
];
export const appRoutingProviders: any[] = [
AuthenticationCallbackActivateGuard
];
最后,在身份验证后导航到您的路线:
this.lock.on('authenticated', (authResult) =>
localStorage.setItem('id_token', authResult.idToken);
this.router.navigate([''], );
);
解决方法 #2 - (angular/core@2.4.1, angular/router@3.4.1, lock@10.7)
与之前所做的类似,但是命令式导航是在警卫本身上完成的,身份验证回调数据作为片段提供,以便 Lock 在处理事件时能够看到此信息。由于导航移至守卫,您不再需要在锁定身份验证事件上进行导航。
创建以下类:
import Injectable from '@angular/core';
import CanActivate from '@angular/router';
import Location from '@angular/common';
import Router from '@angular/router';
@Injectable()
export class AuthenticationCallbackActivateGuard implements CanActivate
constructor(private router: Router, private location: Location)
canActivate()
var path = this.location.path(true);
// You may want to make a more robust check here
var isAuthenticationCallback = path.indexOf("access_token") !== -1;
if (isAuthenticationCallback)
this.router.navigate([''], fragment: path );
return false;
return true;
将其注册为您的家乡路线的守卫:
const appRoutes: Routes = [
path: '', component: HomeComponent, canActivate: [AuthenticationCallbackActivateGuard] ,
path: '**', redirectTo: ''
];
export const appRoutingProviders: any[] = [
AuthenticationCallbackActivateGuard
];
最后,处理认证事件:
this.lock.on('authenticated', (authResult) =>
localStorage.setItem('id_token', authResult.idToken);
);
【讨论】:
解决方法很有效,非常好。我想知道我是否可以将身份验证处理直接放在canActivate
函数中。因为在我看来,我们正在重定向到“”,然后再次重定向到“/home”。
在 Angular 4.2.5、Router 4.2.5 中仍然有效。我现在只是在 AuthenticationCallbackActivateGuard 中使用 JWT 设置 localStorage 而不是转发它。以上是关于如何使用 HashLocationStrategy 和 Auth0 Lock 小部件进行用户登录的主要内容,如果未能解决你的问题,请参考以下文章
Angular2 beta 7 上的 HashLocationStrategy
Location 和 HashLocationStrategy 在 beta.16 中停止工作
Angular Module 共享模块使用 父模块使用多个子模块