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

C#控制台程序对接2FA保护的SharePoint文件传输相关问题

SharePoint 2FA认证与文件操作方案选型问题

我在这个问题上绞尽脑汁,网上有上千种实现方案,但大多已过时或无法运行。微软文档毫无用处,既不清晰解释原理,又引入大量复杂晦涩的术语,还没讲清楚就跳转至其他链接形成网状结构。每当我找到看似可行的方案,却发现该方法已被弃用或即将被弃用。

需求

  • 需作为每日定时任务,在.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 11:44:56