OneDrive文件上传至Teams聊天后其他用户权限错误排查
问题
我按照《Upload large files》教程,通过Microsoft Graph成功将文件上传至用户的OneDrive,UploadAsync操作返回DriveItem对象。随后参考《chatmessage-post》教程中的“Example 4: Send a message with file attachment in it”,利用新创建的DriveItem信息向Teams一对一聊天发送消息,代码如下:
string contentUrl = Combine(myDrive.WebUrl, driveItem.Name); string eTag = driveItem.ETag.Split('{', '}')[1]; var requestBody = new ChatMessage { Subject = null, Body = new ItemBody { ContentType = BodyType.Html, Content = string.Format("Here is my file <attachment id=\"{0}\"></attachment>", eTag), }, Attachments = new List<ChatMessageAttachment> { new ChatMessageAttachment { Id = eTag, ContentType = "reference", ContentUrl = contentUrl, Name = driveItem.Name, TeamsAppId = "{my-app-id}" }, }, }; Task<ChatMessage> postTask = graphClient.Chats[chatId].Messages.PostAsync(requestBody); postTask.Wait();
文件已成功保存至OneDrive,聊天消息也附带了附件链接。但问题是:我作为发起上传和消息发送的用户可以正常打开、下载文件,但聊天中的另一位同组织用户尝试访问时会收到权限错误。
我推测这与OneDrive中文件的共享属性有关,但不清楚如何通过代码将其从“Private”修改为“Sharing”。我注意到DriveItem的Microsoft.Graph.Models.Shared属性,但不知如何成功修改。
我使用“OnBehalfOf”流程,通过Teams JS的microsoftTeams.authentication.getAuthToken获取授权令牌来实例化GraphServiceClient,代码如下:
private async Task<GraphServiceClient> GetOnBehalfOfClient(string authToken){ System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; var options = new OnBehalfOfCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud, }; var accessTokenProvider = new OnBehalfOfCredential( ExchangeTenantId, ExchangeAppId, ExchangeSecret, authToken, options); var scopes = new[] { "https://graph.microsoft.com/.default" }; GraphServiceClient graphClient = new GraphServiceClient(accessTokenProvider, scopes); return graphClient; }
请问为何会出现这种权限差异?如何通过代码修改该DriveItem的权限,使其可被聊天中的另一位用户访问?
解答
权限差异原因
上传到OneDrive的文件默认仅对上传者本人开放访问权限。虽然你在Teams聊天中添加了文件链接,但聊天中的其他用户并未被授予该文件的访问权限,因此他们打开链接时会触发权限错误。另外,DriveItem的Shared属性是只读属性,无法直接修改,必须通过Microsoft Graph的权限授予接口来为目标用户添加访问权限。
代码实现权限授予
要让聊天中的另一位用户能访问该文件,需要完成两个步骤:获取聊天中的目标用户ID,然后为该用户添加文件的读取权限。
1. 获取聊天中的目标用户ID
一对一聊天只有两个成员,排除当前用户后即可得到目标用户ID:
// 获取聊天成员列表 var chatMembers = await graphClient.Chats[chatId].Members.GetAsync(); // 筛选出当前用户之外的成员(一对一聊天仅两人) var targetUser = chatMembers.Value.FirstOrDefault(m => m.UserId != currentUserId); if (targetUser == null) { // 处理未找到目标用户的情况 return; } string targetUserId = targetUser.UserId;
2. 为目标用户添加文件访问权限
调用Microsoft Graph的DriveItem.Permissions接口,授予目标用户读取权限:
// 构造权限请求体 var permissionRequestBody = new Permission { Roles = new List<string> { "read" }, GrantedToV2 = new IdentitySet { User = new Identity { Id = targetUserId } } }; // 添加权限到DriveItem await graphClient.Me.Drive.Items[driveItem.Id].Permissions.PostAsync(permissionRequestBody);
注意事项
- 确保你的应用在Azure AD中配置了足够的权限,比如
Files.ReadWrite.All或Sites.ReadWrite.All(需根据实际场景选择,且需管理员同意)。 - 如果你使用的是用户的OneDrive(
Me.Drive),需确保OnBehalfOf流程获取的令牌包含对应的文件权限范围。 - 权限添加完成后,再发送Teams消息,目标用户即可正常打开附件链接。
内容的提问来源于stack exchange,提问作者lfdevjmp

