C#控制台程序对接2FA保护的SharePoint文件传输相关问题
我在这个问题上绞尽脑汁,网上有上千种实现方案,但大多已过时或无法运行。微软文档毫无用处,既不清晰解释原理,又引入大量复杂晦涩的术语,还没讲清楚就跳转至其他链接形成网状结构。每当我找到看似可行的方案,却发现该方法已被弃用或即将被弃用。
需求
- 需作为每日定时任务,在.NET控制台程序中无人值守运行
- 允许在任务设置时(或每年等长间隔)进行一次基于网页的双因素认证(2FA)
- 能够向不受我直接控制的2FA保护SharePoint站点上传或下载文件,可联系站点所有者申请配置变更
已实现内容
借助视频教程,我已实现控制台程序中Microsoft 365邮箱的2FA认证,认证代码如下:
var scopes = new string[] { "https://graph.microsoft.com/.default" }; var confidentialClient = ConfidentialClientApplicationBuilder .Create(spServiceProfile.ClientID) .WithClientSecret(spServiceProfile.ClientSecret) .WithAuthority(new Uri("https://login.microsoftonline.com/" + spServiceProfile.TenantID + "/")) .Build(); var authResult = await confidentialClient .AcquireTokenForClient(scopes) .ExecuteAsync();
此认证方式需要三个参数:TenantID、ClientID和ClientSecret,视频中说明了获取及配置方法。
要实现文件上传下载,需选择访问SharePoint的API或服务,目前有两个明确选项:CSOM和GraphServiceClient。
我找到了GraphServiceClient的代码(尚未测试):
uploadedFile = (_graphServiceClient .Sites["root"] .Drives["{DriveId}"] .Items["{Id_of_Targetfolder}"] .ItemWithPath(fileToUpload.FileName) .Content.Request() .PutAsync<DriveItem>(ms)).Result;
该方式初看灵活性不如CSOM,我已有可运行的CSOM代码,但引入2FA后认证失效(原代码仅通过用户名密码登录),CSOM代码如下:
var authMgr = new PnP.Framework.AuthenticationManager(spServiceProfile.ClientID, spServiceProfile.UserName, securePassword); using (var rootCtx = authMgr.GetContext(rootSiteUrl)) { Uri webUri = Web.WebUrlFromPageUrlDirect(rootCtx, new Uri(rootSiteUrl + pathUrl)); using (var ctx = authMgr.GetContext(webUri.AbsoluteUri)) { var list = ctx.Web.GetList(pathUrl); var sharepointFolders = list.RootFolder.Folders; ctx.Load(sharepointFolders); ctx.ExecuteQuery(); Folder sharepointRootFolder = null; foreach (var sharepointFolder in sharepointFolders) { //s1 += "\r\\n\\" + folder.Name; if (sharepointFolder.Name.ToLower() == sharepointJob.SharepointRootFolder.ToLower()) { sharepointRootFolder = sharepointFolder; } } if (fileOperation == FileOperationEnum.UploadFolder) { var job = (SharepointTransferFolderJobClass)sharepointJob; // cycle through all files in folder var f_sarr = Directory.EnumerateFiles(job.LocalRootFolder); foreach (var localFilePath in f_sarr) { var localFileName = Path.GetFileName(localFilePath); sharepointRootFolder.UploadFile(localFileName, job.LocalRootFolder, true); } sharepointRootFolder.Update(); ctx.Load(sharepointRootFolder); ctx.ExecuteQueryRetry(); } if (fileOperation == FileOperationEnum.DownloadFolder) { var job = (SharepointTransferFolderJobClass)sharepointJob; foreach (var remoteFile in sharepointRootFolder.Files) { var backupFileName = remoteFile.Name; var sharepointFile = sharepointRootFolder.GetFile(backupFileName); ctx.Load(sharepointFile); ctx.ExecuteQueryRetry(); ClientResult<Stream> stream = sharepointFile.OpenBinaryStream(); ctx.ExecuteQueryRetry(); var destFullFilePath = Path.Combine(job.LocalRootFolder, backupFileName); using (Stream fileStream = new FileStream(destFullFilePath, FileMode.Create)) { CopyStream(stream.Value, fileStream); } } } } }
具体问题
1. CSOM是否即将被弃用?
微软文档中CSOM使用指南顶部有显著警告:“SharePoint加载项模型目前仍受全面支持,但将于2023年底在SharePoint Online中正式弃用。请考虑使用替代扩展选项,让您的扩展更具未来适应性。”
我不确定自己是否在使用SharePoint加载项模型,该警告是否指代整个CSOM,也不确定自己使用的是否为SharePoint Online(而非本地部署)。请问我的使用场景是否属于弃用范围?CSOM长期来看是否会被弃用,还是会保留在生态系统中?
2. 若CSOM不会被弃用,如何将其与我的认证方式结合使用?
我未找到相关资料,智能提示也未提供有效信息。
3. GraphServiceClient是否是更优选择?
Graph似乎处于上升阶段,长期来看可能是更好的选择,但我对其用途尚不明确(GraphQL是否取代了REST?)。我使用的是Graph的边缘功能还是其核心用途?我需要枚举SharePoint文件夹和文件、获取最后修改时间,Graph能否实现这些功能?
我想了解CSOM和GraphServiceClient在SharePoint生态系统中的定位:它们是面向不同场景的工具,会长期共存吗?GraphServiceClient是否会取代CSOM?
补充说明
感谢@Nikolay的回答,现将@Jansenbe在相关文章中的评论附上(以防链接失效):
要全面了解来龙去脉,需要了解一些历史。8年前我们推出了第一个.NET库PnP-Sites-Core,它主要是一组CSOM扩展,后来发展为包含大量功能的集合,帮助SharePoint开发者。该库支持SharePoint Online(SPO)及多个SharePoint本地部署版本。由于越来越多的场景需要非CSOM调用,且旧库不适配现代.NET,同时本地部署使用率下降,我们决定构建新库PnP Core SDK。鉴于PnP-Sites-Core功能庞大,我们无法并行构建包含所有功能的新库来替代它,因此这是一个多年的转型过程,且由开源项目驱动。为此我们推出了PnP Framework,它最初是PnP-Sites-Core的精简版本(移除了所有本地部署相关代码及“遗留”内容)。开发者可以迁移到PnP Framework,同时我们开发PnP Core SDK并将功能从PnP Framework迁移至其中。例如页面API逻辑位于PnP Core SDK中,但仍可通过PnP Framework调用,后者充当代理。
如果您启动新项目,建议使用PnP Core SDK,除非您依赖PnP配置引擎(用于创建和应用站点模板)。使用PnP Core SDK时可能仍会遇到某些功能缺失,但我们会尽快响应,您也可以通过REST/Graph调用自定义API快速解决问题。PnP Core SDK的优势在于抽象了所使用的API(SharePoint REST、Microsoft Graph或SharePoint CSOM),提供统一的开发体验,并能在更完善的Microsoft Graph API可用时替换API实现。
内容的提问来源于stack exchange,提问作者Ben McIntyre

