我目前正在开发 Angular 4 应用程序。
该应用程序使用 Auth0 进行身份验证,其语法与其他身份验证服务的语法非常相似。
认证代码如下:
//auth.services.ts
@Injectable()
export class Auth {
public lock = new Auth0Lock(myConfig.clientID, myConfig.domain, myConfig.lock);
public userProfile: any;
public idToken: string;
public signUpIncomplete: boolean;
// Configure Auth0
private auth0 = new Auth0.WebAuth({
domain: myConfig.domain,
clientID: myConfig.clientID,
redirectUri: myConfig.redirectUri,
responseType: myConfig.responseType
});
// Create a stream of logged in status to communicate throughout app
private loggedIn: boolean;
private loggedIn$ = new BehaviorSubject<boolean>(this.loggedIn);
constructor(private router: Router, private http: Http) {
// Set userProfile attribute of already saved profile
this.userProfile = JSON.parse(localStorage.getItem('profile'));
}
public isAuthenticated(): boolean {
// Check whether the id_token is expired or not
console.log("isAuthenticated");
return tokenNotExpired('id_token');
}
public login(username?: string, password?: string): Promise<any> {
if (!username && !password) {
return;
}
return this.processLogin(username, password);
}
public logout() {
// Remove tokens and profile and update login status subject
localStorage.removeItem('token');
localStorage.removeItem('id_token');
localStorage.removeItem('profile');
this.idToken = '';
this.userProfile = null;
this.setLoggedIn(false);
// Go back to the home rout
this.router.navigate(['/']);
}
public loginWithWidget(): void {
this.lock.show();
}
// Call this method in app.component
// if using path-based routing <== WE ARE USING PATH BASED ROUTING
public handleAuth(): void {
// When Auth0 hash parsed, get profile
this.auth0.parseHash({}, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
// window.location.hash = '';
this._getProfile(authResult);
this.router.navigate(['/']);
} else if (err) {
this.router.navigate(['/']);
console.error(`Error: ${err.error}`);
}
});
}
private setLoggedIn(value: boolean) {
// Update login status subject
this.loggedIn$.next(value);
this.loggedIn = value;
}
private _getProfile(authResult) {
// Use access token to retrieve user's profile and set session
// const lock2 = new Auth0Lock(myConfig.clientID, myConfig.domain, myConfig.lock)
const idToken = authResult.id_token || authResult.idToken;
this.lock.getProfile(idToken, (error, profile) => {
if (error) {
// Handle error
console.error(error.error);
return;
}
// Save session data and update login status subject
this._setSession(authResult, profile);
if (!this.checkUserHasRole(profile)) {
this.router.navigate(['/signup/complete']);
}
});
}
private _setSession(authResult, profile) {
// Save session data and update login status subject
localStorage.setItem('token', authResult.access_token || authResult.accessToken);
localStorage.setItem('id_token', authResult.id_token || authResult.idToken);
localStorage.setItem('profile', JSON.stringify(profile));
this.idToken = authResult.id_token || authResult.idToken;
this.setLoggedIn(true);
this.userProfile = profile;
this.checkUserHasRole(profile);
}
private processLogin(username?: string, password?: string): Promise<any> {
const options = {
client_id: myConfig.clientID,
connection: postConfig.body.connection,
grant_type: 'password',
username,
password,
scope: myConfig.scope
};
const headers = new Headers();
headers.append('content-type', 'application/json');
const reqOpts = new RequestOptions({
method: RequestMethod.Post,
url: postConfig.urlLogin,
headers,
body: options
});
return this.http.post(postConfig.urlLogin, options, reqOpts)
.toPromise()
.then(this.extractData)
.then((data) => { this._getProfile(data); })
.catch(this.handleLoginError);
}
...
}
我遇到的问题是 isAuthenticated
方法在页面加载时被调用了 1000 多次。此外,每次我在窗口对象中移动鼠标时都会调用它。
虽然我一步一步地遵循了 Auth0 的教程,但我认为这不是预期的行为,因为它将会并且已经影响了应用程序的性能。
经常调用 isAuthenticated 的原因可能是什么?我是否必须实现一个计时器,在指定时间后定期进行检查,或者我是否必须实现一个观察者?我的代码中是否有任何明显的错误?
最佳答案
isAuthenticated
被调用这么多次的原因取决于调用它的组件,这里没有。 isAuthenticated
从未在此服务中被调用一次。
改为设置路由器防护,由 Angular API 调用 CanActivate
。这将在路由激活时调用,重定向可能在路由组件加载之前发生故障,并且只会被调用一次。使用它来调用 service.isAuthenticated
。
login.guard.ts
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { Auth } from './auth.service';
@Injectable()
export class LoginGuard implements CanActivate {
constructor(public auth: Auth, protected router: Router) { }
canActivate() {
if (!this.auth.isAuthenticated()) {
this.router.navigate(['/']);
return false;
}
return true;
}
在你的路由定义中
export const routes: Routes = [
{ path: '', component: SomeComponent },
{ path: 'main', component: ProtectedComponent, canActivate: [LoginGuard] }
]
在任何情况下都不应该被调用 1000 次。我猜你的组件或注入(inject)树中正在进行一些循环。
https://stackoverflow.com/questions/44005163/