Angular2 auth guard 带有 http 请求和 observables
Angular2 auth guard with http request and observables
我目前正在实施一个带有 spring 引导作为后端的 angular2 示例应用程序。我在前端身份验证保护机制和可观察对象方面遇到了一些问题。
我正在努力实现:
- 当有人进入受保护的路线时,auth guard 应该检查用户是否
已经在 auth 服务变量中设置
- 如果未设置,则应发出 http 请求以检查会话是否可用
- 服务方法应该 return 一个 true/false 值(异步,因为可能有 http 请求)
- 如果服务returns false auth guard应该重定向到登录页面
- auth guard 应该 return true/false 所以路由可以被激活或不被激活
我的代码目前看起来像这样(顺便说一句,我正在使用 RC5。):
Auth Guard
import {Injectable} from "@angular/core";
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router";
import {Observable, Subject} from "rxjs/Rx";
import {AuthService} from "./auth.service";
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
var authenticated = this.authService.isAuthenticated();
var subject = new Subject<boolean>();
authenticated.subscribe(
(res) => {
console.log("onNext guard: "+res);
if(!res && state.url !== '/signin') {
console.log("redirecting to signin")
this.router.navigate(['/signin']);
}
subject.next(res);
});
return subject.asObservable();
}
}
授权服务
import {Injectable} from "@angular/core";
import {User} from "./user.interface";
import {Router} from "@angular/router";
import {Http, Response, Headers} from "@angular/http";
import {environment} from "../environments/environment";
import {Observable, Observer, Subject} from "rxjs/Rx";
@Injectable()
export class AuthService {
private authenticatedUser : User;
constructor(private router: Router, private http: Http) {}
signupUser(user: User) {
}
logout() {
//do logout stuff
this.router.navigate(['/signin']);
}
isAuthenticated() : Observable<boolean> {
var subject = new Subject<boolean>();
if (this.authenticatedUser) {
subject.next(true);
} else {
this.http.get(environment.baseUrl + '/user')
.map((res : Response) => res.json())
.subscribe(res => {
console.log("next: returning true");
this.authenticatedUser = User.ofJson(res);
subject.next(true);
}, (res) => {
console.log("next: returning false");
subject.next(false);
});
}
return subject.asObservable();
}
}
问题是:即使我已登录,守卫也不允许路由器组件激活。
感谢您的帮助!
改变
return subject.asObservable();
至
return subject.asObservable().first();
路由器等待 observable 完成。 first()
在第一个事件后完成。
我目前正在实施一个带有 spring 引导作为后端的 angular2 示例应用程序。我在前端身份验证保护机制和可观察对象方面遇到了一些问题。
我正在努力实现:
- 当有人进入受保护的路线时,auth guard 应该检查用户是否 已经在 auth 服务变量中设置
- 如果未设置,则应发出 http 请求以检查会话是否可用
- 服务方法应该 return 一个 true/false 值(异步,因为可能有 http 请求)
- 如果服务returns false auth guard应该重定向到登录页面
- auth guard 应该 return true/false 所以路由可以被激活或不被激活
我的代码目前看起来像这样(顺便说一句,我正在使用 RC5。):
Auth Guard
import {Injectable} from "@angular/core";
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router";
import {Observable, Subject} from "rxjs/Rx";
import {AuthService} from "./auth.service";
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
var authenticated = this.authService.isAuthenticated();
var subject = new Subject<boolean>();
authenticated.subscribe(
(res) => {
console.log("onNext guard: "+res);
if(!res && state.url !== '/signin') {
console.log("redirecting to signin")
this.router.navigate(['/signin']);
}
subject.next(res);
});
return subject.asObservable();
}
}
授权服务
import {Injectable} from "@angular/core";
import {User} from "./user.interface";
import {Router} from "@angular/router";
import {Http, Response, Headers} from "@angular/http";
import {environment} from "../environments/environment";
import {Observable, Observer, Subject} from "rxjs/Rx";
@Injectable()
export class AuthService {
private authenticatedUser : User;
constructor(private router: Router, private http: Http) {}
signupUser(user: User) {
}
logout() {
//do logout stuff
this.router.navigate(['/signin']);
}
isAuthenticated() : Observable<boolean> {
var subject = new Subject<boolean>();
if (this.authenticatedUser) {
subject.next(true);
} else {
this.http.get(environment.baseUrl + '/user')
.map((res : Response) => res.json())
.subscribe(res => {
console.log("next: returning true");
this.authenticatedUser = User.ofJson(res);
subject.next(true);
}, (res) => {
console.log("next: returning false");
subject.next(false);
});
}
return subject.asObservable();
}
}
问题是:即使我已登录,守卫也不允许路由器组件激活。
感谢您的帮助!
改变
return subject.asObservable();
至
return subject.asObservable().first();
路由器等待 observable 完成。 first()
在第一个事件后完成。