NativeScript+Angular如何传递授权状态、构建角色权限及解决Google OAuth错误
问题修复方案
1. 跨组件登录状态无法获取问题
错误原因
你定义的isLogged是脱离AppComponent实例的独立函数,运行时this指向完全不符合预期,同时AppComponent内的isAuthenticated是组件私有状态,其他组件没有直接访问权限。
修复步骤
第一步:改造AuthService,全局托管登录状态
使用RxJS的BehaviorSubject存储响应式登录状态,所有组件共享同一份状态数据:
// auth.service.ts 新增/修改代码 import { BehaviorSubject } from 'rxjs'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { // 私有Subject,仅允许服务内部更新状态 private isAuthenticatedSubject = new BehaviorSubject<boolean>(false); // 对外暴露可观察对象,供组件订阅状态变更 public isAuthenticated$ = this.isAuthenticatedSubject.asObservable(); // 原有登录逻辑扩展 tnsOauthLogin(provider: string): Promise<ITnsOAuthTokenResult> { // 保留原有登录逻辑,登录成功后更新全局状态 return 原有登录Promise逻辑.then(result => { this.isAuthenticatedSubject.next(true); return result; }) } // 原有登出逻辑扩展 tnsOauthLogout(): void { // 保留原有登出逻辑,登出后更新全局状态 this.isAuthenticatedSubject.next(false); } // 可选:同步获取当前登录状态 getIsAuthenticated(): boolean { return this.isAuthenticatedSubject.value; } }
第二步:简化AppComponent逻辑
不再本地维护isAuthenticated状态,直接复用服务中的全局状态:
// app.component.ts 修改后代码 import { IAuthenticated } from './interfaces/IAuthenticated' @Component({ selector: 'ns-app', templateUrl: 'app.component.html', }) export class AppComponent implements OnInit, IAuthenticated { constructor(public authService: AuthService, private router: Router) {} onLogin() { this.authService.tnsOauthLogin('google').then(() => { this.router.navigate(['/home']); }) .catch((e) => console.log(e)) }; onLogout() { this.authService.tnsOauthLogout(); this.router.navigate(['/home']); } }
对应模板修改状态判断逻辑,用async管道自动订阅状态:
<StackLayout row="0" class="nt-drawer__header"> <Image class="nt-drawer__header-image fas t-36" src="font://"></Image> <Button class="google-signin" style="background-color: #30BCFF; color: #FFF; border-radius: 5; font-size: 20;" *ngIf="(authService.isAuthenticated$ | async) === false" text="Zaloguj się z Google" (tap)="onLogin()"></Button> <Button class="google-signout" style="background-color: #30BCFF; color: #FFF; border-radius: 5; font-size: 20;" *ngIf="(authService.isAuthenticated$ | async) === true" text="Wyloguj" (tap)="onLogout()"></Button> <Label class="nt-drawer__header-footnote" *ngIf="(authService.isAuthenticated$ | async) === true" text="{{ userEmail }}"></Label> </StackLayout>
第三步:改造需要读取登录状态的业务组件
直接注入AuthService即可获取全局状态,无需导入外部函数:
// knowledge-base.component.ts 修改后代码 export class KnowledgeBaseComponent implements OnInit { constructor(public authService: AuthService) {} ngOnInit(): void {} }
对应模板简化逻辑:
<StackLayout> <Button *ngIf="authService.isAuthenticated$ | async" text="Dodaj wpis"></Button> </StackLayout>
2. Google OAuth Scope报错问题
错误原因
你使用的旧版OAuth库不识别短名称格式的scope,需要传入Google API的完整scope路径。
修复方案
修改scope配置为完整路径,同时确认Google Cloud控制台配置:
export function configureOAuthProviderGoogle(): TnsOaProvider { const googleProviderOptions: TnsOaProviderOptionsGoogle = { openIdSupport: 'oid-full', clientId: '替换为你的Google Cloud OAuth客户端ID', redirectUri: '替换为你在控制台配置的重定向地址', urlScheme: '替换为你的应用自定义Scheme', // 替换为完整路径scope,兼容旧版API scopes: [ "openid", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" ] }; const googleProvider = new TnsOaProviderGoogle(googleProviderOptions); return googleProvider; }
如果修改后仍报错,请进入Google Cloud控制台对应项目的「API和服务」页面,确认已启用「Google People API」,同时检查OAuth客户端ID的应用类型、包名、签名SHA1与NativeScript项目配置完全一致。
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

