在MS Teams中切换SharePoint页面编辑/显示模式时SPFx请求失败
问题描述
在网页版MS Teams的标签页中查看关联的SharePoint页面时,切换至编辑模式后,通过@microsoft/sp-http包提供的MSGraphClientFactory发起的Graph API请求会失败。原因是该工具会自动从SharePoint的AcquireOBOToken端点获取令牌,请求时传入的clientId会在切换编辑模式时发生变更,导致令牌获取失败。刷新iframe后Web部件可恢复正常,此问题出现在SPFx 1.19.0版本中。
重现步骤
- 创建标准ReactJS SPFx Web部件
- 安装
@microsoft/sp-http库 - 在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> ); } }
- 构建、打包解决方案并上传至SharePoint应用目录
- 将Web部件添加到与Teams频道关联的SharePoint网站首页
- 在MS Teams中打开该页面,确认邮箱地址正常显示
- 进入页面编辑模式并保存
- 观察到邮箱地址无法正常显示
解决方案
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
相关产品推荐
相关产品推荐

