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

如何通过无人值守C#应用访问启用MFA的SharePoint 365 Excel文件

无人值守C#应用访问启用MFA的SharePoint Online中Excel文件的解决方案

问题背景

我们拥有一个启用了MFA的SharePoint 365站点,该站点的某个项目文件夹中有一份Excel文件,希望通过无人值守C#应用读取并处理它。交互式操作时可完成MFA验证后打开文件,但尝试以下5种方案均抛出异常:

文件URL:

string excelUrl = @"https://company.sharepoint.com/teams/Projects/DocCtrl/Project.xlsm";

所有案例中WebClient统一请求头:

webClient.Headers[HttpRequestHeader.UserAgent] = "Other";
webClient.Headers["X-FORMS_BASED_AUTH_ACCEPTED"] = "f";

案例1

using (WebClient webClient = new WebClient())
{
    webClient.UseDefaultCredentials = true;
    using (MemoryStream memoryStream = new MemoryStream(webClient.DownloadData(excelUrl)))
        using (SpreadsheetDocument xlDocument = SpreadsheetDocument.Open(memoryStream, false))
            readAndProcess(xlDocument);
}

异常信息:webClient.DownloadData(excelUrl)处抛出:远程服务器返回错误: (401) 未授权。

案例2

(注:此方案需硬编码或存储密码,希望避免)

using (WebClient webClient = new WebClient())
{
    webClient.Credentials = new NetworkCredential(@"emailId@company.com", @"Password", "Domain");
    using (MemoryStream memoryStream = new MemoryStream(webClient.DownloadData(excelUrl)))
        using (SpreadsheetDocument xlDocument = SpreadsheetDocument.Open(memoryStream, false))
            readAndProcess(xlDocument);
}

异常信息:webClient.DownloadData(excelUrl)处抛出:远程服务器返回错误: (401) 未授权。

案例3

(注:此方案需硬编码或存储密码,希望避免)

using (WebClient webClient = new WebClient())
{
    SecureString securePwd = new SecureString();
    foreach (char chr in @"Password")
        securePwd.AppendChar(chr);
    webClient.Credentials = new SharePointOnlineCredentials(@"emailId@company.com", securePwd);
    using (MemoryStream memoryStream = new MemoryStream(webClient.DownloadData(excelUrl)))
        using (SpreadsheetDocument xlDocument = SpreadsheetDocument.Open(memoryStream, false))
            readAndProcess(xlDocument);
}

异常信息:webClient.DownloadData(excelUrl)处抛出:请求已中止: 请求已取消。合作伙伴返回无效登录名或密码错误。更多信息,请参阅联合身份验证错误处理场景。

案例4

(注:此方案会弹出MFA验证窗口,不符合无人值守需求,希望避免)

using (WebClient webClient = new WebClient())
{
    var authManager = new OfficeDevPnP.Core.AuthenticationManager();
    ClientContext ctx = authManager.GetWebLoginClientContext(@"https://company.sharepoint.com");
    ctx.Load(ctx.Web, w => w.Title);
    ctx.ExecuteQuery();
    using (MemoryStream memoryStream = new MemoryStream(webClient.DownloadData(excelUrl)))
        using (SpreadsheetDocument xlDocument = SpreadsheetDocument.Open(memoryStream, false))
            readAndProcess(xlDocument);
}

异常信息:webClient.DownloadData(excelUrl)处抛出:远程服务器返回错误: (401) 未授权。

案例5

(注:此方案仍会弹出MFA验证窗口,不符合无人值守需求,希望避免)

using (WebClient webClient = new WebClient())
{
    var authManager = new OfficeDevPnP.Core.AuthenticationManager();
    ClientContext ctx = authManager.GetWebLoginClientContext(@"https://company.sharepoint.com");
    SecureString securePwd = new SecureString();
    foreach (char chr in @"Password")
        securePwd.AppendChar(chr);
    ctx.Credentials = new SharePointOnlineCredentials(@"emailId@company.com", securePwd);
    ctx.Load(ctx.Web, w => w.Title);
    ctx.ExecuteQuery();
    using (MemoryStream memoryStream = new MemoryStream(webClient.DownloadData(excelUrl)))
        using (SpreadsheetDocument xlDocument = SpreadsheetDocument.Open(memoryStream, false))
            readAndProcess(xlDocument);
}

异常信息:ctx.ExecuteQuery()处抛出:合作伙伴返回无效登录名或密码错误。更多信息,请参阅联合身份验证错误处理场景。

解决方案

关于应用密码

应用密码仅适用于传统MFA(非现代身份验证)场景,当前大多数SharePoint Online租户已启用现代身份验证,应用密码无法绕过MFA验证,因此不能解决无人值守访问的问题。

推荐方案:使用Azure AD应用程序权限(客户端凭据流)

这是无人值守访问启用MFA的SharePoint Online的标准方案,步骤如下:

  1. 在Azure AD中注册应用程序

    • 登录Azure门户,进入Azure Active Directory → 应用注册 → 新建注册。
    • 设置应用名称,选择"账户仅限于此组织目录中的账户",无需重定向URI。
    • 注册完成后,记录客户端ID和租户ID。
  2. 创建客户端密码

    • 在应用注册的"证书和密码"选项卡,新建客户端密码,设置有效期,记录生成的密码值(仅显示一次)。
  3. 授予应用程序权限

    • 进入应用注册的"API权限"选项卡,点击"添加权限" → 选择"SharePoint" → "应用权限"。
    • 添加Sites.Read.All(根据需求选择更精细的权限,如Sites.Selected),然后点击"授予管理员同意"。
  4. C#代码实现

方式1:使用Microsoft Graph SDK下载文件

using Azure.Identity;
using Microsoft.Graph;
using System.IO;

var clientId = "你的客户端ID";
var tenantId = "你的租户ID";
var clientSecret = "你的客户端密码";
var excelFilePath = "/teams/Projects/DocCtrl/Project.xlsm"; // SharePoint站点相对路径

var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(credential);

// 获取文件内容
var stream = await graphClient.Sites["company.sharepoint.com,teams/Projects,{site-id}"]
    .Drive
    .Root
    .ItemWithPath(excelFilePath)
    .Content
    .Request()
    .GetAsync();

// 读取并处理Excel文件
using (var memoryStream = new MemoryStream())
{
    await stream.CopyToAsync(memoryStream);
    memoryStream.Position = 0;
    using (var xlDocument = SpreadsheetDocument.Open(memoryStream, false))
    {
        readAndProcess(xlDocument);
    }
}

方式2:使用SharePoint CSOM + Azure AD身份验证

using Microsoft.SharePoint.Client;
using System.Security;
using Azure.Identity;
using System.Net.Http.Headers;

var siteUrl = "https://company.sharepoint.com/teams/Projects";
var clientId = "你的客户端ID";
var tenantId = "你的租户ID";
var clientSecret = "你的客户端密码";

// 获取访问令牌
var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var token = await credential.GetTokenAsync(new Azure.Core.TokenRequestContext(new[] { "https://sharepoint.com/.default" }));

// 使用CSOM访问SharePoint
using (var ctx = new ClientContext(siteUrl))
{
    ctx.ExecutingWebRequest += (s, e) =>
    {
        e.WebRequestExecutor.RequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Token);
    };

    // 获取文件
    var file = ctx.Web.GetFileByServerRelativeUrl("/teams/Projects/DocCtrl/Project.xlsm");
    ctx.Load(file);
    ctx.ExecuteQuery();

    // 下载文件内容
    var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(ctx, file.ServerRelativeUrl);
    using (var memoryStream = new MemoryStream())
    {
        fileInfo.Stream.CopyTo(memoryStream);
        memoryStream.Position = 0;
        using (var xlDocument = SpreadsheetDocument.Open(memoryStream, false))
        {
            readAndProcess(xlDocument);
        }
    }
}

关键说明

  • 客户端凭据流无需用户交互,完全适合无人值守应用。
  • 权限需遵循最小权限原则,避免过度授权。
  • 客户端密码需妥善存储,建议使用Azure Key Vault等安全存储方案,不要硬编码到代码中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:07:19