Keycloak场景下Promise转Observable实现 解决AuthGuard返回值不匹配问题
解决步骤
首先导入rxjs对应的转换工具:
import { from, of, Observable } from 'rxjs'; import { catchError, map } from 'rxjs/operators';
你现有代码存在两个不符合类型要求的问题:
- 未认证时调用的
keycloak.login()返回Promise类型,没有转换为Observable,也没有对应返回值 - 后续的权限校验结果是布尔值,没有包装为Observable类型
修改后的完整代码如下:
export class AuthGuard extends KeycloakAuthGuard { constructor( protected readonly router: Router, protected readonly keycloak: KeycloakService ) { super(router, keycloak); } public isAccessAllowed( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> { // 未登录的场景 if (!this.authenticated) { // 使用from方法将login返回的Promise转为Observable return from(this.keycloak.login({ redirectUri: window.location.origin + state.url, })).pipe( // 登录调用后会自动跳转到登录页,实际不会执行到该逻辑,返回false满足类型要求即可 map(() => false), // 捕获登录异常,返回false阻止访问 catchError(() => of(false)) ); } const requiredRoles = route.data.roles; // 路由没有配置角色要求直接放行 if (!(requiredRoles instanceof Array) || requiredRoles.length === 0) { // 使用of方法将布尔值包装为Observable return of(true); } // 校验角色权限,结果用of包装为Observable return of(requiredRoles.every((role) => this.roles.includes(role))); } }
核心转换逻辑说明
- Promise转Observable:直接用rxjs提供的
from()方法包裹Promise实例即可完成转换 - 静态值转Observable:布尔值、字符串等静态值用
of()方法包裹即可转换为对应类型的Observable - 调用
keycloak.login()后会自动跳转至身份认证页,当前页面后续逻辑不会执行,pipe内的返回值仅用于满足类型校验要求
内容的提问来源于stack exchange,提问作者Zelars Green
相关产品推荐
相关产品推荐

