Logo

SharePoint CSOM 获取凭据

photo

2025年05月23日

现在基本都是用多因子认证的居多,所以如果你遇到了多因子认证的客户,获取SharePoint的凭据的方式只剩下以下三种:

1:弹窗式的操作

如果你希望还是采用以前弹窗式的操作来获取,那么参考如下:

引用:SharePointPnPCoreOnline 老版的3.25版本

采用如下代码:

string siteUrl = "https://site-admin.sharepoint.com";
var authManager = new OfficeDevPnP.Core.AuthenticationManager();
ClientContext ctx = authManager.GetWebLoginClientContext(siteUrl);

2:通过 SharePoint 仅限应用令牌授予访问权限

这个方案已经废弃了,但是你还是要用的话,参考如下流程:

SharePoint 仅限应用是设置应用主体的旧模型,但仍非常相关。 此模型适用于 SharePoint Online 和本地 SharePoint (2013/2016/2019/subscription edition) ,非常适合准备应用程序以便从本地 SharePoint 迁移到 SharePoint Online。 以下步骤演示如何设置具有租户完全控制权限的应用主体,但也可以使用此方法仅授予读取权限。

自 2023 年 11 月 27 日起,已停用 Azure ACS (访问控制 Services for SharePoint Online) ,请查看完整的停用公告以了解详细信息。 在 SharePoint 上下文之外使用 Azure ACS 已于 2018 年 11 月 7 日停用,现已停用。

停用意味着该功能不会获得任何新投资,但仍受支持。 生命周期结束意味着该功能将停用,不再可供使用。

对于新租户,默认禁用使用仅 ACS 应用访问令牌的应用。 建议使用新式且更安全的仅限 Azure AD 应用的模型。 但是,可以通过运行“set-spotenant -DisableCustomAppAuthentication $false”来更改行为, (需要最新的 SharePoint 管理员 PowerShell) 。

设置具有租户权限的仅限应用主体

默认情况下,除非 SharePoint 租户管理员明确允许,否则网站集管理员无法在 AppRegNew.aspx 中向 Azure ACS 注册外接程序。有关详细信息,请参阅 Set-SPOTenant

导航到租户 ((例如 https://contoso.sharepoint.com) )中的网站,然后 (调用appregnew.aspx页面,例如 https://contoso.sharepoint.com/_layouts/15/appregnew.aspx) 。 在此页中,填写剩余信息,如下面的屏幕截图所示。

& 机密创建新的客户端 ID

按 Create 后,将显示客户端 ID 和客户端密码,将检索到的信息 (客户端 ID 和客户端密码存储) ,因为在下一步中将需要此信息!

下一步是向新建的主体授予权限。 因为要授予的是租户范围内的权限,所以只能通过租户管理网站上的 appinv.aspx 页面授予此权限。 可以通过 https://contoso-admin.sharepoint.com/_layouts/15/appinv.aspx 来访问此网站。 在页面加载后,添加客户端 ID,并查找已创建的主体:

向新主体授予权限

必须提供描述所需权限的权限 XML,才能授予权限。 由于此应用需要能够访问所有网站,并且还需要结合使用仅限应用访问和搜索功能,因此需要下列权限:

<AppPermissionRequests AllowAppOnlyPolicy="true">
  <AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="FullControl" />
</AppPermissionRequests>

单击“创建”后,将会看到权限许可对话框。 按“信任它”,以授予权限:

使用 appregnew.aspx

请保护所创建的客户端 ID/密码组合,就像保护管理员帐户一样。 使用此客户端 ID/密码,可以在 SharePoint Online 环境中读取/更新所有数据!

完成准备工作后,接下来下一章节将继续介绍如何通过客户端 ID 和密码组合使用所创建的应用主体。

通过 PnP PowerShell 使用此主体

如果要将生成的仅限应用注册与 PnP PowerShell 结合使用,可以通过使用以下工具连接到本地 SharePoint 或 SharePoint Online 环境来实现此操作:

Connect-PnPOnline -Url https://contoso.sharepoint.com/sites/demo -ClientId [Your Client ID] -ClientSecret "[Your Client Secret]"

PnP PowerShell 是一种开放源代码解决方案,其中包含为其提供支持的活动社区。 没有用于 Microsoft 开放源代码工具支持的 SLA。

使用 PnP 框架库在应用程序中使用此主体

在第一步中,添加 PnP 框架库 nuget 包: https://www.nuget.org/packages/PnP.Framework。 完成此操作后,可以使用以下代码构造:

string siteUrl = "https://contoso.sharepoint.com/sites/demo";
using (var cc = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, "[Your Client ID]", "[Your Client Secret]"))
{
    cc.Load(cc.Web, p => p.Title);
    cc.ExecuteQuery();
    Console.WriteLine(cc.Web.Title);
};

在应用程序中使用此主体而不使用 PnP 框架库

创建并许可主体后,便可以使用此主体的 ID 和密码来请求获取访问权限。 TokenHelper.cs 类将使用应用程序的配置文件中的 ID 和机密。

using Microsoft.SharePoint.Client;
using System;

namespace AzureACSAuth
{
    class Program
    {
        static void Main(string[] args)
        {
            string siteUrl = "https://contoso.sharepoint.com/sites/demo";

            //Get the realm for the URL
            string realm = TokenHelper.GetRealmFromTargetUrl(new Uri(siteUrl));

            //Get the access token for the URL.  
            string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, new Uri(siteUrl).Authority, realm).AccessToken;

            //Create a client context object based on the retrieved access token
            using (ClientContext cc = TokenHelper.GetClientContextWithAccessToken(siteUrl, accessToken))
            {
                cc.Load(cc.Web, p => p.Title);
                cc.ExecuteQuery();
                Console.WriteLine(cc.Web.Title);
            }
        }
    }
}

示例 app.config 如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!-- Use AppRegNew.aspx and AppInv.aspx to register client id with secret -->
    <add key="ClientId" value="[Your Client ID]" />
    <add key="ClientSecret" value="[Your Client Secret]" />
  </appSettings>
</configuration>

可以将 AppForSharePointOnlineWebToolkit NuGet 包添加到解决方案中,从而在项目中轻松插入 TokenHelper.cs 类。

3:通过 Azure AD 仅限应用令牌授予访问权限(推荐)

使用 SharePoint Online 时,可以在 Azure ID 中定义应用程序,并能向这些应用程序授予对 SharePoint 的访问权限,还可以向应用程序授予对 Office 365 中其他所有服务的访问权限。 如果使用的是 SharePoint Online,则此模型是首选模型,如果在本地使用 SharePoint,则必须通过基于的 Azure ACS 使用 SharePoint Only 模型,如此 所述。

自 2023 年 11 月 27 日起,已停用 Azure ACS (访问控制 Services for SharePoint Online) ,请查看完整的停用公告以了解详细信息。 在 SharePoint 上下文之外使用 Azure ACS 已于 2018 年 11 月 7 日停用,现已停用。

停用意味着该功能不会获得任何新投资,但仍受支持。 生命周期结束意味着该功能将停用,不再可供使用。

为 Azure AD 应用设置仅限应用访问

在 Azure AD 中执行仅限应用访问时,通常都是使用证书来请求获取访问权限:只要拥有证书及其私钥,就可以使用应用,并拥有向应用授予的权限。 下面逐步介绍了如何设置此模型。

现在可以将 Azure AD 应用配置为,使用仅限应用访问令牌调用 SharePoint Online。 为此,必须创建和配置自签名 X.509 证书,用于对应用进行 Azure AD 身份验证,同时请求获取仅限应用访问令牌。 首先,必须创建自签名的 X.509 证书,可以使用 Windows SDK 中提供的 makecert.exe 工具,通过提供的 PowerShell 脚本创建,该脚本没有生成证书的依赖项,或者使用 PnP PowerShell 命令。 使用 PowerShell 脚本是首选方法,本章节对此进行了介绍。

请务必使用管理员权限运行以下脚本。

使用此脚本创建自签名证书的具体步骤:

.\Create-SelfSignedCertificate.ps1 -CommonName "MyCompanyName" -StartDate 2017-10-01 -EndDate 2019-10-01

 备注

日期采用 ISO 日期格式:YYYY-MM-dd

证书密钥 algoritm 必须是 RSA,这是目前唯一受支持的算法

可以复制下面的实际脚本:

#Requires -RunAsAdministrator
<#
.SYNOPSIS
Creates a Self Signed Certificate for use in server to server authentication
.DESCRIPTION
.EXAMPLE
PS C:\> .\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21
This will create a new self signed certificate with the common name "CN=MyCert". During creation you will be asked to provide a password to protect the private key.
.EXAMPLE
PS C:\> .\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21 -Password (ConvertTo-SecureString -String "MyPassword" -AsPlainText -Force)
This will create a new self signed certificate with the common name "CN=MyCert". The password as specified in the Password parameter will be used to protect the private key
.EXAMPLE
PS C:\> .\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21 -Force
This will create a new self signed certificate with the common name "CN=MyCert". During creation you will be asked to provide a password to protect the private key. If there is already a certificate with the common name you specified, it will be removed first.
#>
Param(

   [Parameter(Mandatory=$true)]
   [string]$CommonName,

   [Parameter(Mandatory=$true)]
   [DateTime]$StartDate,

   [Parameter(Mandatory=$true)]
   [DateTime]$EndDate,

   [Parameter(Mandatory=$false, HelpMessage="Will overwrite existing certificates")]
   [Switch]$Force,

   [Parameter(Mandatory=$false)]
   [SecureString]$Password
)

# DO NOT MODIFY BELOW

function CreateSelfSignedCertificate(){

    #Remove and existing certificates with the same common name from personal and root stores
    #Need to be very wary of this as could break something
    if($CommonName.ToLower().StartsWith("cn="))
    {
        # Remove CN from common name
        $CommonName = $CommonName.Substring(3)
    }
    $certs = Get-ChildItem -Path Cert:\LocalMachine\my | Where-Object{$_.Subject -eq "CN=$CommonName"}
    if($certs -ne $null -and $certs.Length -gt 0)
    {
        if($Force)
        {

            foreach($c in $certs)
            {
                remove-item $c.PSPath
            }
        } else {
            Write-Host -ForegroundColor Red "One or more certificates with the same common name (CN=$CommonName) are already located in the local certificate store. Use -Force to remove them";
            return $false
        }
    }

    $name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
    $name.Encode("CN=$CommonName", 0)

    $key = new-object -com "X509Enrollment.CX509PrivateKey.1"
    $key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
    $key.KeySpec = 1
    $key.Length = 2048
    $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
    $key.MachineContext = 1
    $key.ExportPolicy = 1 # This is required to allow the private key to be exported
    $key.Create()

    $serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
    $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") # Server Authentication
    $ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
    $ekuoids.add($serverauthoid)
    $ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
    $ekuext.InitializeEncode($ekuoids)

    $cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
    $cert.InitializeFromPrivateKey(2, $key, "")
    $cert.Subject = $name
    $cert.Issuer = $cert.Subject
    $cert.NotBefore = $StartDate
    $cert.NotAfter = $EndDate
    $cert.X509Extensions.Add($ekuext)
    $cert.Encode()

    $enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
    $enrollment.InitializeFromRequest($cert)
    $certdata = $enrollment.CreateRequest(0)
    $enrollment.InstallResponse(2, $certdata, 0, "")
    return $true
}

function ExportPFXFile()
{
    if($CommonName.ToLower().StartsWith("cn="))
    {
        # Remove CN from common name
        $CommonName = $CommonName.Substring(3)
    }
    if($Password -eq $null)
    {
        $Password = Read-Host -Prompt "Enter Password to protect private key" -AsSecureString
    }
    $cert = Get-ChildItem -Path Cert:\LocalMachine\my | where-object{$_.Subject -eq "CN=$CommonName"}

    Export-PfxCertificate -Cert $cert -Password $Password -FilePath "$($CommonName).pfx"
    Export-Certificate -Cert $cert -Type CERT -FilePath "$CommonName.cer"
}

function RemoveCertsFromStore()
{
    # Once the certificates have been been exported we can safely remove them from the store
    if($CommonName.ToLower().StartsWith("cn="))
    {
        # Remove CN from common name
        $CommonName = $CommonName.Substring(3)
    }
    $certs = Get-ChildItem -Path Cert:\LocalMachine\my | Where-Object{$_.Subject -eq "CN=$CommonName"}
    foreach($c in $certs)
    {
        remove-item $c.PSPath
    }
}

if(CreateSelfSignedCertificate)
{
    ExportPFXFile
    RemoveCertsFromStore
}

系统会提示提供用于加密私钥的密码,.PFX 文件和 .CER 文件都会导出到当前文件夹。

还可以通过 New-PnPAzureCertificate 命令生成自签名证书。

下一步是在与 Office 365 租户关联的 Azure Active Directory 租户中注册 Azure AD 应用。 为此,请使用租户全局管理员组的用户成员的帐户打开Office 365 Admin中心 https://admin.microsoft.com () 。 在 Office 365 管理中心的左侧树视图中,单击“管理中心”组下的“Azure Active Directory”链接。 随即打开的新浏览器选项卡中将显示 Microsoft Azure 门户。 如果这是首次使用帐户访问 Azure 门户,必须注册新 Azure 订阅,同时提供一些信息以及付款时所需的信用卡。 不过,别担心,使用 Azure AD 和注册 Office 365 应用程序无需支付任何费用。 实际上,这些都是免费功能。 有权访问 Azure 门户后,依次选择“Azure Active Directory”部分和“应用注册”选项。 有关详细信息,请参阅下图。

显示 Azure AD 门户

“应用注册”选项卡中列出了在租户中注册的 Azure AD 应用。 单击边栏选项卡左上角的“新注册”按钮。 接下来,命名应用,并单击边栏选项卡底部的“注册”。

新建 Azure AD 应用

 重要

创建应用程序后,请复制“应用程序 (客户端) ID”,因为稍后将需要它。

现在,依次单击左侧菜单栏中的“API 权限”和“添加权限”按钮。 此时,新边栏选项卡显示。 在其中,可以选择将向此应用授予的权限。 即选择:

  • SharePoint
    • 应用权限
      • 网站
        • Sites.FullControl.All

单击底部的蓝色“添加权限”按钮,以向应用添加权限。 “应用权限”是向作为“仅应用”运行的应用授予的权限。

向 Azure AD 应用授予权限

最后一步是将之前创建的证书“连接到”应用程序。 单击左侧菜单栏中的“证书和机密”。 单击“上传证书”按钮,选择之前生成的 .CER 文件,并单击“添加”来上传它。

若要确认证书是否已成功注册,请单击左侧菜单栏中的“清单”。 搜索“keyCredentials”属性。 它应如下所示:

JSON复制

  "keyCredentials": [
    {
      "customKeyIdentifier": "<$base64CertHash>",
      "endDate": "2021-05-01T00:00:00Z",
      "keyId": "<$guid>",
      "startDate": "2019-05-01T00:00:00Z",
      "type": "AsymmetricX509Cert",
      "usage": "Verify",
      "value": "<$base64Cert>",
      "displayName": "CN=<$name of your cert>"
     }
  ],

如果看到类似这样的部分,表明证书已成功添加。

在此示例中,必须在租户中获得管理员同意,才能使用 Sites.FullControl.All 应用权限。 为此,请再次单击左侧菜单中的“API 权限”。 在底部,你会看到“授予同意”部分。 单击“授予 {{organization name}} 管理员同意”按钮,然后单击顶部显示的“是”按钮确认操作。

向 Azure ad 应用程序授予 API 权限

通过 PnP PowerShell 使用此主体

若要通过 PnP PowerShell 使用此 AAD“仅应用”主体,可以在安装 PnP PowerShell 模块后,使用下面的代码连接到 SharePoint Online 环境:

PowerShell复制

Connect-PnPOnline -ClientId <$application client id as copied over from the AAD app registration above> -CertificatePath '<$path to the PFX file generated by the PowerShell script above>' -CertificatePassword (ConvertTo-SecureString -AsPlainText "<$password assigned to the generated certificate pair above>" -Force) -Url https://<$yourtenant>.sharepoint.com -Tenant "<$tenantname>.onmicrosoft.com"

现在可以通过 PnP PowerShell 使用此证书“仅应用”信任,对 SharePoint Online 环境执行操作。

PnP PowerShell 是一种开放源代码解决方案,其中包含为其提供支持的活动社区。 没有用于 Microsoft 开放源代码工具支持的 SLA。

使用 SharePoint PnP 框架库在应用程序中使用此主体

在第一步中,添加 PnP 框架库 NuGet 包: https://www.nuget.org/packages/PnP.Framework

完成此操作后,可以使用以下代码构造:

using PnP.Framework;
using System;

namespace AzureADCertAuth
{
    class Program
    {
        static void Main(string[] args)
        {
            var authManager = new AuthenticationManager("<application id>", "c:\\temp\\mycert.pfx", "<password>", "contoso.onmicrosoft.com");
            using (var cc = authManager.GetContext("https://contoso.sharepoint.com/sites/demo"))
            {
                cc.Load(cc.Web, p => p.Title);
                cc.ExecuteQuery();
                Console.WriteLine(cc.Web.Title);
            };
        }
    }
}

PnP Framework 是一个开放源代码解决方案,其活动社区为其提供支持。 没有用于 Microsoft 开放源代码工具支持的 SLA。

使用 PnP 框架库在 Powershell 脚本中使用此主体

使用 Azure 自动化 Runbook 时,首先使用“证书”选项(在“共享资源”下)添加证书 (.pfx),然后使用 Get-AutomationCertificate cmdlet 检索要在脚本中使用的证书。

需要先将 PnP.Framework 模块添加到自动化帐户。 此模块包含进行身份验证调用所需的一切内容。

# path to installed modules
$path = "C:\Modules\User\SharePointPnPPowerShellOnline"

# reference to needed assemblies
Add-Type -Path "$path\Microsoft.SharePoint.Client.dll"
Add-Type -Path "$path\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "$path\PnP.Framework.dll"
Add-Type -Path "$path\PnP.Core.dll"
Add-Type -Path "$path\Microsoft.Identity.Client.dll"

# reference to the certificate
$cert = Get-AutomationCertificate -Name 'NameOfCertificate'

# set the variables
$siteUrl = "https://<tenant>.sharepoint.com"
$appId = "<guid of the App>"
$domain = "<tenant>.onmicrosoft.com"
$azureEnv = [PnP.Framework.AzureEnvironment]::Production

try {
    # instantiate the object
    $clientContext = $null
    $authManager = new-object PnP.Framework.AuthenticationManager($appId, $cert, $domain, $null, $azureEnv)

    # configure the object
    $clientContext = $authManager.GetContext($siteUrl)

    # do some stuff
    $clientContext.Load($clientContext.Web)
    $clientContext.ExecuteQuery()
    $clientContext.Web.Title
}
catch {
    # catch error if needed
}
finally {
    $clientContext.Dispose()
}

在应用程序中使用此主体,并使用 Azure KeyVault 来存储证书并使用 Azure 函数进行检索

托管标识添加到 Azure 函数并为此标识提供对 KeyVault 的访问权限(针对机密的 GET 权限)。

下面对同一 AuthenticationManager 方法的调用略有不同,其中我们传递的是实际证书,而不是证书的路径。 添加了一个额外的函数,以使用 Azure 函数的托管标识从 KeyVault 检索证书,此检索是无缝和透明的,因为“magic”发生在 DefaultAzureCredential 中。

此示例使用两个库来访问密钥保管库:

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.SharePoint.Client;
using System.Security.Cryptography.X509Certificates;

using (var cc = new PnP.Framework.AuthenticationManager(
    "<application id>",
    GetKeyVaultCertificate("kv-spo", "AzureAutomationSPOAccess"),
    "contoso.onmicrosoft.com").GetContext("https://contoso.sharepoint.com/sites/demo"))
{
    cc.Load(cc.Web, p => p.Title);
    cc.ExecuteQuery();
    log.Info("Via PnP, we have site: " + cc.Web.Title);
};

static X509Certificate2 GetKeyVaultCertificate(string keyvaultName, string name)
{
    // Some steps need to be taken to make this work
    // 1. Create a KeyVault and upload the certificate
    // 2. Give the Function App the permission to GET certificates via Access Policies in the KeyVault
    // 3. Call an explicit access token request to the management resource to https://vault.azure.net and use the URL of our Keyvault in the GetSecret method
    Uri keyVaultUri = new Uri($"https://{keyvaultName}.vault.azure.net/");

    var client = new SecretClient(keyVaultUri, new DefaultAzureCredential());
    KeyVaultSecret secret = client.GetSecret(name);

    return new X509Certificate2(Convert.FromBase64String(secret.Value), string.Empty, X509KeyStorageFlags.MachineKeySet);
}

通过 Pnp 现代化扫描仪使用此主体

现在已创建 Azure Active Directory 应用注册,继续按照此处的步骤操作来通过工具使用此主体。

常见问题

除了使用证书以外,还能使用其他方法对我的 Azure AD 应用实现仅限应用访问吗?

不能,其他所有选项都已被 SharePoint Online 屏蔽,并会导致生成“访问遭拒”消息。

参考文章:通过 Azure AD 仅限应用令牌授予访问权限 | Microsoft Learn

橙子主题打折出售

其实我不卖,主要是这里是放广告的,所以就放了一个
毕竟主题都没做完,卖了也是坑.

购买它
本文为原创文章,请注意保留出处!

留言板

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

在现代的Web应用程序中,提供自动语言检测功能可以显著提升用户体验。本文将介绍如何实现一个具有自动语...实现一个自动语言检测的翻译工具

热门文章

WordPress 后台编辑器样式实现直接预览 在WordPress3.0以后,有一个新的实用功能:你可以更改默认后台编辑器(TinyMCE)的样...WordPress后台编辑器样式实现直接预览 作者:Pastore Antonio
1567 浏览量
C#图片处理 通常对一幅图片的处理包括:格式变换,缩放(Scale),翻转(Rotate),截取(Clip),滤镜...C#图片处理 作者:Pastore Antonio
1527 浏览量
【干货】Chrome插件(扩展)开发全攻略 写在前面我花了将近一个多月的时间断断续续写下这篇博文,并精心写下完整demo,写博客的辛苦大家懂的...【干货】Chrome插件(扩展)开发全攻略 作者:Pastore Antonio
1524 浏览量
memcached 处理 多端口:https://blog.csdn.net/Erica_1230/article/deta...memcached处理 作者:Pastore Antonio
1519 浏览量
Windows 休眠 浏览量:1,585 作者:Pastore Antonio
1511 浏览量