我正在尝试使用sessionStorage存储在AppComponent的ngInit中检索的用户信息。 但是,由于此检索使用httpClient,因此即使在存储键值之前,也可以在另一个组件中访问它。这是唯一一次设置此密钥。
@Injectable()
export class AuthService {
public currentuser = new BehaviorSubject<User>(<User>JSON.parse(sessionStorage.getItem('currentuser')));
constructor(private _http: HttpClient, private _trace: TraceService) { }
public authenticate(): void {
this._http.get<User>(AppSettings.AuthUrl, {withCredentials: true})
.subscribe(user => {
sessionStorage.setItem('currentuser', JSON.stringify(user));
this.currentuser.next(user);
},
e => {
if (e.status === 403) {
this.currentuser.next(null);
this._trace.handleAuthError(e);
} else {
this.currentuser.next(null);
this._trace.handleError('Authenticating...', e);
}
});
}
}
在auth guard组件中我有
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private _router: Router,
private _authService: AuthService) { }
public canActivate() {
this._authService.currentuser.subscribe(u => {
if (u === null) {
this._router.navigateByUrl(AppSettings.NotAuthenticatedRoute);
return false;
}});
return true;
}
}
路由模块
const routes: Routes = [ { path: AppSettings.LegalTermsRoute, component: LegalTermComponent, canActivate: [AuthGuard] }];
在AppComponent
中 ngOnInit(): void {
this._authService.authenticate();
}
问题在于,我不是以正确的方式设置此订阅,当应用程序出现时,auth guard会阻止LegalTermComponent
答案 0 :(得分:1)
sessionStorage.getItem
会返回一个值,因此我不确定您是否可以使用Observable.from
,但我认为它适合您。这更像是Observable.of
- 无论哪种方式,这都会将一个值转换为一个立即发出然后完成的Observable,这不是你想要的。
您需要创建一个自定义Observable,该值在可用时发出值。 BehaviorSubject
适用于此,因为只要您订阅它,您将获得其最后一个值,即使您在设置值后碰巧订阅,也可以获得所述值。
export class AuthService {
currentuser = new BehaviorSubject<User>(sessionStorage.getItem('currentuser') as User);
authenticate() {
// Do whatever authenticate usually does ... this is an example
this.http.post<User>('/auth').subscribe(user => this.currentuser.next(user));
}
/* your other methods and properties ... */
我也会避免在组件中实现副作用(例如更新会话存储),而是在服务中执行。
答案 1 :(得分:0)
我认为这样就发布了我的回答,以防万一这可能对我的情况有帮助,这是Web API中的简单Windows身份验证。我使用Kendo - 所以使用加载微调器来使事情同步。
// app.component.ts
ngOnInit(): void {
sessionStorage.clear();
sessionStorage.setItem('requestedRoute', window.location.pathname);
this._router.navigateByUrl(AppSettings.AuthRoute, {skipLocationChange: true});
}
// AuthRoute -> auth.component.ts
@Component({
selector: 'app-auth',
template: `
<div *ngIf="isAuthenticating()" class="k-i-loading"></div>
<div style="padding:20px"><h4>Authenticating...</h4><div>
<div kendoDialogContainer></div>
`,
styles: []
})
ngOnInit() {
this._authService.authenticate().subscribe((user: User) => {
if (user !== undefined) {
user.isAuthencated = true;
sessionStorage.setItem('currentuser', JSON.stringify(user));
this._router.navigateByUrl(sessionStorage.getItem('requestedRoute'));
}
});
}
public isAuthenticating() {
return this._authService.isAuthenticating;
}
//auth.service.ts
public isAuthenticating = true; // loading spinner
constructor(private _http: HttpClient, private _trace: TraceService) { }
public authenticate(): Observable<User> {
this.isAuthenticating = true;
return this._http.get<User>(AppSettings.AuthUrl, {withCredentials: true})
.catch<any, User>((e, u) => this._trace.handleAuthError(e))
.catch<any, User>(this._trace.handleError('GET ' + AppSettings.AuthUrl, []))
.finally(() => this.isAuthenticating = false);
}
//auth.guard.ts
public canActivate(): Observable<boolean> | boolean {
const user = <User>JSON.parse(sessionStorage.getItem('currentuser'));
if (user !== null && user.isAuthencated) {
return true;
} else {
this._router.navigateByUrl(AppSettings.NotAuthenticatedRoute);
return false;
}
}