You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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://&#xf2bd;"></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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 10:06:01