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

在MS Teams中切换SharePoint页面编辑/显示模式时SPFx请求失败

在MS Teams内编辑SharePoint页面时Graph API请求失败问题的解决

问题描述

在网页版MS Teams的标签页中查看关联的SharePoint页面时,切换至编辑模式后,通过@microsoft/sp-http包提供的MSGraphClientFactory发起的Graph API请求会失败。原因是该工具会自动从SharePoint的AcquireOBOToken端点获取令牌,请求时传入的clientId会在切换编辑模式时发生变更,导致令牌获取失败。刷新iframe后Web部件可恢复正常,此问题出现在SPFx 1.19.0版本中。

重现步骤

  1. 创建标准ReactJS SPFx Web部件
  2. 安装@microsoft/sp-http库
  3. 在React组件中添加Graph API请求代码:
import * as React from 'react';
import type { IHelloWorldProps } from './IHelloWorldProps';
import { MSGraphClientFactory } from '@microsoft/sp-http';

export default class HelloWorld extends React.Component<IHelloWorldProps, {email:string}> {
  constructor(props:IHelloWorldProps){
    super(props);
    this.state = {
      email: ""
    };
  }
  public componentDidMount(): void {
    const { serviceScope } = this.props;
    serviceScope.whenFinished(async ()=>{
      const msGraphClientFactory = serviceScope.consume(MSGraphClientFactory.serviceKey);
      const msGraphClient = await msGraphClientFactory.getClient('3');
      const me = await msGraphClient.api(`/me`).get();
      this.setState({
        email: me.mail
      });
    });
  }
  public render(): React.ReactElement<IHelloWorldProps> {
    return (
      <div>
        {this.state.email && <p>Your email is {this.state.email}</p>}
      </div>
    );
  }
}
  1. 构建、打包解决方案并上传至SharePoint应用目录
  2. 将Web部件添加到与Teams频道关联的SharePoint网站首页
  3. 在MS Teams中打开该页面,确认邮箱地址正常显示
  4. 进入页面编辑模式并保存
  5. 观察到邮箱地址无法正常显示

解决方案

1. 手动指定固定Client ID

跳过MSGraphClientFactory自动获取clientId的逻辑,手动传入Web部件注册的固定Client ID来获取令牌:

import * as React from 'react';
import type { IHelloWorldProps } from './IHelloWorldProps';
import { MSGraphClientFactory } from '@microsoft/sp-http';
import { SPHttpClient, SPHttpClientConfigurations } from '@microsoft/sp-http';

export default class HelloWorld extends React.Component<IHelloWorldProps, {email:string}> {
  // 替换为你的Web部件对应的固定Client ID
  private readonly FIXED_CLIENT_ID = "你的Web部件Client ID";

  constructor(props:IHelloWorldProps){
    super(props);
    this.state = {
      email: ""
    };
  }

  public componentDidMount(): void {
    const { serviceScope } = this.props;
    serviceScope.whenFinished(async ()=>{
      const msGraphClientFactory = serviceScope.consume(MSGraphClientFactory.serviceKey);
      const msGraphClient = await msGraphClientFactory.getClient('3', {
        authProvider: {
          getToken: async () => {
            const spHttpClient = serviceScope.consume(SPHttpClient.serviceKey);
            const response = await spHttpClient.post(
              `${this.props.context.pageContext.web.absoluteUrl}/_api/SP.OAuth.Token/AcquireOBOToken`,
              SPHttpClientConfigurations.v1,
              {
                headers: {
                  'Content-Type': 'application/json',
                  'Accept': 'application/json'
                },
                body: JSON.stringify({
                  clientId: this.FIXED_CLIENT_ID,
                  resource: 'https://graph.microsoft.com'
                })
              }
            );
            const tokenResult = await response.json();
            return tokenResult.access_token;
          }
        }
      });
      const me = await msGraphClient.api(`/me`).get();
      this.setState({
        email: me.mail
      });
    });
  }

  public render(): React.ReactElement<IHelloWorldProps> {
    return (
      <div>
        {this.state.email && <p>你的邮箱是 {this.state.email}</p>}
      </div>
    );
  }
}

2. 监听编辑状态变更,重新发起请求

监听页面编辑状态的变化,当状态切换时重新初始化Graph Client并获取数据:

import * as React from 'react';
import type { IHelloWorldProps } from './IHelloWorldProps';
import { MSGraphClientFactory } from '@microsoft/sp-http';
import { ServiceScope } from '@microsoft/sp-core-library';

export default class HelloWorld extends React.Component<IHelloWorldProps, {email:string}> {
  constructor(props:IHelloWorldProps){
    super(props);
    this.state = {
      email: ""
    };
  }

  public componentDidMount(): void {
    const { serviceScope, context } = this.props;
    
    // 监听页面编辑状态变更
    context.pageContext.legacyPageContext.onChange(() => {
      this.fetchUserEmail(serviceScope);
    });

    this.fetchUserEmail(serviceScope);
  }

  private async fetchUserEmail(serviceScope: ServiceScope): Promise<void> {
    try {
      await serviceScope.whenFinished(async ()=>{
        const msGraphClientFactory = serviceScope.consume(MSGraphClientFactory.serviceKey);
        const msGraphClient = await msGraphClientFactory.getClient('3');
        const me = await msGraphClient.api(`/me`).get();
        this.setState({
          email: me.mail
        });
      });
    } catch (error) {
      console.error('获取用户邮箱失败:', error);
      // 可添加重试逻辑,比如间隔几秒后重新请求
    }
  }

  public render(): React.ReactElement<IHelloWorldProps> {
    return (
      <div>
        {this.state.email && <p>你的邮箱是 {this.state.email}</p>}
      </div>
    );
  }
}

3. 升级SPFx版本

SPFx 1.19.0之后的版本已修复部分与Teams集成时的身份验证问题,尝试升级到最新稳定版本(如1.20及以上),重新构建并部署Web部件,验证问题是否解决。

内容的提问来源于stack exchange,提问作者Jackson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:48:11