如何从C#控制台应用程序对启用SSO的SharePoint进行身份认证?
SharePoint启用SSO(通常基于Azure AD)时,无需硬编码用户名密码,可通过MSAL.NET + Microsoft Graph API实现认证、文件夹创建和文件上传,以下是分场景的实操方案:
一、核心认证方案
1. 桌面/交互式应用
适合有UI的客户端应用,通过弹出SSO登录窗口完成认证:
首先安装NuGet包:Microsoft.Identity.Client、Microsoft.Graph
using Microsoft.Identity.Client; using Microsoft.Graph; var clientId = "你的Azure AD应用客户端ID"; var tenantId = "你的租户ID"; var scopes = new[] { "https://graph.microsoft.com/Sites.ReadWrite.All" }; // 初始化公共客户端应用 var publicClientApp = PublicClientApplicationBuilder .Create(clientId) .WithTenantId(tenantId) .WithRedirectUri("http://localhost") .Build(); // 获取SSO令牌(自动唤起企业登录界面) var authResult = await publicClientApp.AcquireTokenInteractive(scopes).ExecuteAsync(); // 构造Graph客户端 var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMsg) => { requestMsg.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken); }));
2. 服务端/后台应用(无人值守)
适合无UI的后台服务,使用Azure AD应用密钥完成认证:
同样安装上述NuGet包,代码如下:
using Microsoft.Identity.Client; using Microsoft.Graph; var clientId = "你的Azure AD应用客户端ID"; var tenantId = "你的租户ID"; var clientSecret = "你的Azure AD应用密钥"; var scopes = new[] { "https://graph.microsoft.com/.default" }; // 初始化机密客户端应用 var confidentialClientApp = ConfidentialClientApplicationBuilder .Create(clientId) .WithTenantId(tenantId) .WithClientSecret(clientSecret) .Build(); // 获取应用级令牌 var authResult = await confidentialClientApp.AcquireTokenForClient(scopes).ExecuteAsync(); // 构造Graph客户端 var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMsg) => { requestMsg.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken); }));
二、创建多级文件夹
通过Graph API递归创建文件夹,支持路径自动拆分:
var siteId = "你的SharePoint站点ID"; var driveId = "文档库的Drive ID"; var targetFolderPath = "/项目文档/2024Q3/技术资料"; // 目标文件夹路径 var folderSegments = targetFolderPath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); DriveItem parentFolder = null; foreach (var folderName in folderSegments) { // 检查文件夹是否已存在 var existingFolders = await graphClient.Sites[siteId].Drives[driveId].Root.Children .Request() .Filter($"name eq '{folderName}' and folder ne null") .GetAsync(); if (existingFolders.Count == 0) { // 创建新文件夹,冲突时自动重命名 var newFolder = new DriveItem { Name = folderName, Folder = new Folder(), AdditionalData = new Dictionary<string, object> { {"@microsoft.graph.conflictBehavior", "rename"} } }; parentFolder = await graphClient.Sites[siteId].Drives[driveId].Root.Children.Request().AddAsync(newFolder); } else { parentFolder = existingFolders.First(); } }
三、上传文件(PDF/Excel/Word等)
支持任意文件类型,直接流式上传:
var localFilePath = @"C:\本地文件\项目方案.pdf"; // 本地文件路径 var fileName = Path.GetFileName(localFilePath); using (var fileStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read)) { var uploadedItem = await graphClient.Sites[siteId].Drives[driveId].Items[parentFolder.Id] .ItemWithPath(fileName) .Content .Request() .PutAsync<DriveItem>(fileStream); }
四、关键注意事项
- 权限配置:在Azure AD门户中,给应用分配对应的Graph权限:交互式应用用
Sites.ReadWrite.All(委派权限),后台应用用Sites.ReadWrite.All(应用权限),并完成管理员同意。 - 站点/Drive ID获取:如果不知道站点ID,可通过站点域名查询:
await graphClient.Sites.GetByPath("/sites/你的站点域名", "你的租户域名").Request().GetAsync();Drive ID可通过站点的文档库查询:await graphClient.Sites[siteId].Drives.Request().GetAsync()。 - SharePoint本地版(ADFS SSO):若为本地SharePoint,可使用
SharePointPnPCoreOnline库,通过AuthenticationManager.GetADFSContext(siteUrl, adfsMetadataUrl)获取认证上下文,再调用PnP API操作文件夹和文件。
内容的提问来源于stack exchange,提问作者blue
相关产品推荐
相关产品推荐

