Angular OpenId Connect:第一次渲染发生在令牌准备好之前
Angular OpenId Connect : first rendering occurs before token is ready
我正在使用 Angular 10 和 angular-auth-oidc-client (https://github.com/damienbod/angular-auth-oidc-client).
如果用户未登录(无登录按钮),我希望将用户重定向到身份验证服务器。
我这样做了:
// component :
export class AppComponent implements OnInit {
constructor(public authService: AuthService) {
}
async ngOnInit(): Promise<void> {
return this.authService.checkAuthAndLogin();
}
}
// service :
@Injectable({
providedIn: 'root'
})
export class AuthService {
async checkAuthAndLogin(): Promise<void> {
await this.oidcSecurityService.checkAuth().subscribe((auth) => {
if (!auth) {
this.login();
}
console.log('is authenticated', auth);
});
}
}
// http client interceptor to send tokens to my backend :
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(
private oidcSecurityService: OidcSecurityService
) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.oidcSecurityService.getToken()}`
}
});
return next.handle(request);
}
}
它正在工作,但第一次渲染总是失败,我必须刷新页面才能让它工作。它在第一次加载时向我的后端服务器发送一个空令牌。
我找到了一个解决方法,就是在 init 方法中等待 500 毫秒,但它看起来很脏:
export class AppComponent implements OnInit {
constructor(public authService: AuthService) {
}
loggedIn = false;
async ngOnInit(): Promise<void> {
return this.authService.checkAuthAndLogin().then(() => {
return new Promise(resolve => setTimeout(resolve, 500)).then(() => {
this.loggedIn = true;
});
});
}
}
在我的应用程序组件模板中:
<div *ngIf="loggedIn">
[...]
</div>
它的行为就像 oidcSecurityService.checkAuth() 提前解析,而令牌尚未准备好。
是否有更清洁的解决方案?
谢谢
我认为您没有返回正确的结果:
checkAuthAndLogin(): Promise<string> {
return new Promise((res, rej) => {
this.oidcSecurityService.checkAuth().subscribe((auth) => { // don't user await with observables
if (!auth) {
this.login();
rej('Auth is failed')
}
console.log('is authenticated', auth);
if (auth) res('authenticated');
});
})
}
您调用 checkAuthAndLogin
时似乎没有返回任何内容。我不确定您的身份验证服务一起做了什么。但是您需要等待身份验证令牌收到,然后使其登录为真并解决承诺,或者您可以使用行为主题来实现它。
我删除了服务中的 async/await(编辑:和 gnInit 中的异步),我用 ng-if 保留了 isLogged
布尔值(仍然不知道我需要做什么),现在它正在工作:
checkAuthAndLogin(): Observable<void> {
return this.oidcSecurityService.checkAuth().pipe(map((auth) => {
if (!auth) {
this.login();
}
console.log('is authenticated', auth);
}));
}
// componenent :
ngOnInit(): Promise<void> {
return this.authService.checkAuthAndLogin().toPromise().then(() => {
this.loggedIn = true;
});
}
我正在使用 Angular 10 和 angular-auth-oidc-client (https://github.com/damienbod/angular-auth-oidc-client).
如果用户未登录(无登录按钮),我希望将用户重定向到身份验证服务器。
我这样做了:
// component :
export class AppComponent implements OnInit {
constructor(public authService: AuthService) {
}
async ngOnInit(): Promise<void> {
return this.authService.checkAuthAndLogin();
}
}
// service :
@Injectable({
providedIn: 'root'
})
export class AuthService {
async checkAuthAndLogin(): Promise<void> {
await this.oidcSecurityService.checkAuth().subscribe((auth) => {
if (!auth) {
this.login();
}
console.log('is authenticated', auth);
});
}
}
// http client interceptor to send tokens to my backend :
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(
private oidcSecurityService: OidcSecurityService
) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.oidcSecurityService.getToken()}`
}
});
return next.handle(request);
}
}
它正在工作,但第一次渲染总是失败,我必须刷新页面才能让它工作。它在第一次加载时向我的后端服务器发送一个空令牌。
我找到了一个解决方法,就是在 init 方法中等待 500 毫秒,但它看起来很脏:
export class AppComponent implements OnInit {
constructor(public authService: AuthService) {
}
loggedIn = false;
async ngOnInit(): Promise<void> {
return this.authService.checkAuthAndLogin().then(() => {
return new Promise(resolve => setTimeout(resolve, 500)).then(() => {
this.loggedIn = true;
});
});
}
}
在我的应用程序组件模板中:
<div *ngIf="loggedIn">
[...]
</div>
它的行为就像 oidcSecurityService.checkAuth() 提前解析,而令牌尚未准备好。
是否有更清洁的解决方案?
谢谢
我认为您没有返回正确的结果:
checkAuthAndLogin(): Promise<string> {
return new Promise((res, rej) => {
this.oidcSecurityService.checkAuth().subscribe((auth) => { // don't user await with observables
if (!auth) {
this.login();
rej('Auth is failed')
}
console.log('is authenticated', auth);
if (auth) res('authenticated');
});
})
}
您调用 checkAuthAndLogin
时似乎没有返回任何内容。我不确定您的身份验证服务一起做了什么。但是您需要等待身份验证令牌收到,然后使其登录为真并解决承诺,或者您可以使用行为主题来实现它。
我删除了服务中的 async/await(编辑:和 gnInit 中的异步),我用 ng-if 保留了 isLogged
布尔值(仍然不知道我需要做什么),现在它正在工作:
checkAuthAndLogin(): Observable<void> {
return this.oidcSecurityService.checkAuth().pipe(map((auth) => {
if (!auth) {
this.login();
}
console.log('is authenticated', auth);
}));
}
// componenent :
ngOnInit(): Promise<void> {
return this.authService.checkAuthAndLogin().toPromise().then(() => {
this.loggedIn = true;
});
}