使用 ACS 在本地 SharePoint 网站上授权低信任提供程序托管的加载项
先决条件
确保满足以下条件:
本地 SharePoint 开发环境。 请参阅设置 SharePoint 加载项的本地开发环境。
Office 365 SharePoint 网站。 如果还没有开发环境,并且想要快速设置开发环境,可以在 Office 365 上为 SharePoint 外接程序设置开发环境。
Visual Studio 以远程方式或在运行 SharePoint 的计算机上安装,工作负荷为 Office/SharePoint 开发。 早期版本的 Visual Studio 需要 组件 Microsoft Office Developer Tools for Visual Studio 。 此处提供了此组件的最新版本,适用于 Visual Studio 2013,此处适用于 Visual Studio 2015。
重要
Azure Active Directory 端停用 ACS 不影响此 SharePoint 功能。 有关详细信息,请参阅以下文章:停用 Azure 访问控制对 SharePoint 加载项的影响。
配置 SharePoint 的本地安装以使用 ACS
下图显示了在本地网站上运行的提供程序托管加载项整体架构内启用所需连接的四个步骤。 还显示了加载项运行时的 OAuth 令牌流。
通过 Office 365 SharePoint 网站对 SharePoint 的本地安装使用 ACS
在本地 SharePoint 场中创建 ACS 代理。
将本地服务器的签名证书安装到 Office 365 租户。
将要运行外接程序的 SharePoint 场上的站点的完全限定域名添加到 Office 365 租赁的服务主体名称集合中。
在 SharePoint 场中创建加载项管理代理。
以下函数执行了配置本地 SharePoint 网站以使用 ACS 的所有工作。 如果需要删除之前的配置,还可以使用此函数执行一些清理任务。 在 PowerShell 中有多种方式可运行此函数。 下面介绍一种方法。
配置本地 SharePoint 网站以使用 ACS
在本地 SharePoint 服务器上,将下面) 提供的函数Connect-SPFarmToAAD (的代码复制到名为 MySharePointFunctions.psm1 的文本文件中,并将其保存到以下文件夹的一个或另一个, (而不是同时) 。 如果包括尚不存在的文件夹,可能需要创建部分路径。 请注意,在这两种情况下,路径中最低一级的文件夹必须与文件具有相同的文件名。
提示
文件必须另存为 ANSI 格式(而非 UTF-8)。 加载非 ANSI 格式的文件时,PowerShell 可能会出现语法错误。 Windows 记事本默认将其保存为 ANSI。 如果使用任何其他编辑器保存文件,请务必将其另存为 ANSI。
C:\users\username\documents\windowspowershell\modules\MySharePointFunctions
,其中 username 是即将执行文件的场管理员。C:\windows\system32\windowspowershell\V1.0\modules\MySharePointFunctions
函数Connect-SPFarmToAAD需要 NuGet 包 MSOnlineExt 才能正常工作,请使用下面的 cmdlet 进行安装。
Install-Module -Name MSOnlineExt
以管理员身份打开 SharePoint 命令行管理程序,并运行以下 cmdlet,验证 MySharePointFunctions 模块是否已列出。
Get-Module -listavailable
运行以下 cmdlet 以导入模块。
Import-Module MySharePointFunctions
运行以下 cmdlet,验证 Connect-SPFarmToAAD 函数是否已作为模块的一部分列出。
Get-Command -module MySharePointFunctions
运行以下 cmdlet,验证 Connect-SPFarmToAAD 函数是否已加载。
ls function:\ | where {$_.Name -eq "Connect-SPFarmToAAD"}
运行
Connect-SPFarmToAAD
函数。 请务必提供必需的参数,以及所有适用于你的开发人员环境的可选参数。 请参阅下一节,获取详细信息和示例。
Connect-SPFarmToAAD 函数参数
参数 | 值 |
---|---|
-AADDomain (必需) |
注册 Office 365 网站时创建的 *.onmicrosoft.com 域 (yourcustomdomain.onmicrosoft.com)。 当脚本提示你进行身份验证时,请使用为此域创建的用户名和密码:username@yourcustomdomain.onmicrosoft.com。 |
-SharePointOnlineUrl (必需) |
Office 365 SharePoint 网站的 URL (_https://yourcustomdomain_.sharepoint.com ) 。 请注意,父域不是 onmicrosoft.com。 |
-SharePointWeb (有时必需) |
本地 SharePoint Web 应用程序的完整 URL(包括协议),你将在其中运行提供程序托管的加载项。此功能仅将本地场中的一个 SharePoint Web 应用程序添加到 ACS。 如果没有为此项指定值,脚本将选择场中的第一个 Web 应用程序。 如果使用的是可使用通配符进行定义的主机名网站集 (HNSC)(如 http://*.contoso.com),则可以将该字符串用作此参数的值。 如果 Web 应用程序具有 Internet 区域的备用访问映射 (AAM),则必须将该 AAM URL 用于此参数。 如果没有为 HTTPS 配置 SharePoint Web 应用程序,则必须将 HTTP 用作协议,而且必须使用 -AllowOverHttp 开关(请参阅本表后面的部分)。 如果要在场中的更多 Web 应用程序上运行使用 ACS 的提供程序托管的加载项,需要将它们添加到服务主体名称集合中。 Connect-SPFarmToAAD 函数后跟的 Windows PowerShell 脚本显示了如何将场上的所有 Web 应用程序添加到服务主体名称集合中。 |
-AllowOverHttp (可选) |
如果正在使用开发人员环境并且不想对外接程序使用 SSL,请使用此开关。如果没有为 HTTPS 配置 SharePoint Web 应用程序,则必须使用此开关。 |
-O365Credentials (可选) |
第一个字符是大写的“O”,不是零。 如果需要重复运行脚本进行调试,使用此开关后,便不必每次都手动输入 O365 名称和密码。 在使用此参数之前,必须使用以下 cmdlet 创建将分配给该参数的凭据对象: $User = "username@yourcustomdomain.onmicrosoft.com"$PWord = ConvertTo-SecureString -String "the_password" -AsPlainText -Force$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord 使用 $Credential 作为参数的值 -O365Credentials 。 |
-Verbose (可选) |
此开关会生成更详细的反馈,如果函数无法正常工作,且需要重新运行函数以进行调试,则此开关可能很有用。 |
-RemoveExistingACS (可选) |
如果要替换与 Microsoft Azure Active Directory 的现有连接,请使用此开关。 如果已经在场中创建了一个 ACS 代理,则它会删除现有 ACS 代理。 |
-RemoveExistingSTS (可选) |
如果要替换与 Microsoft Azure Active Directory 的现有连接,请使用此开关。 它会删除从较早的 ACS 连接遗留下来的现有可信安全令牌颁发者。 |
-RemoveExistingSPOProxy (可选) |
如果要替换与 Microsoft Azure Active Directory 的现有连接,请使用此开关。 如果已经在场中创建了一个加载项管理代理,则它会删除现有加载项管理代理。 |
-RemoveExistingAADCredentials (可选) |
如果要替换 Office 365 SharePoint 网站,请使用此开关。 |
示例如下:
Connect-SPFarmToAAD -AADDomain 'MyO365Domain.onmicrosoft.com' -SharePointOnlineUrl https://MyO365Domain.sharepoint.com
Connect-SPFarmToAAD -AADDomain 'MyO365Domain.onmicrosoft.com' -SharePointOnlineUrl https://MyO365Domain.sharepoint.com -SharePointWeb https://fabrikam.com
Connect-SPFarmToAAD -AADDomain 'MyO365Domain.onmicrosoft.com' -SharePointOnlineUrl https://MyO365Domain.sharepoint.com -SharePointWeb http://northwind.com -AllowOverHttp
Connect-SPFarmToAAD -AADDomain 'MyO365Domain.onmicrosoft.com' -SharePointOnlineUrl https://MyO365Domain.sharepoint.com -SharePointWeb http://northwind.com -AllowOverHttp -RemoveExistingACS -RemoveExistingSTS -RemoveExistingSPOProxy -RemoveExistingAADCredentials
MySharePointFunctions.psm1 的内容
function Connect-SPFarmToAAD {
param(
[Parameter(Mandatory)][String] $AADDomain,
[Parameter(Mandatory)][String] $SharePointOnlineUrl,
#Specify this parameter if you don't want to use the default SPWeb returned
[Parameter()][String] $SharePointWeb,
[Parameter()][System.Management.Automation.PSCredential] $O365Credentials,
#Use these switches if you're replacing an existing connection to AAD.
[Parameter()][Switch] $RemoveExistingACS,
[Parameter()][Switch] $RemoveExistingSTS,
[Parameter()][Switch] $RemoveExistingSPOProxy,
#Use this switch if you're replacing the Office 365 SharePoint site.
[Parameter()][Switch] $RemoveExistingAADCredentials,
#Use this switch if you don't want to use SSL when you launch your app.
[Parameter()][Switch] $AllowOverHttp
)
#Prompt for credentials right away.
if (-not $O365Credentials) {
$O365Credentials = Get-Credential -Message "Admin credentials for $AADDomain"
}
Add-PSSnapin Microsoft.SharePoint.PowerShell
#Import the Microsoft Online Services Sign-In Assistant.
Import-Module -Name MSOnline
#Import the Microsoft Online Services Module for Windows PowerShell.
Import-Module MSOnlineExt -force -verbose
#Set values for Constants.
New-Variable -Option Constant -Name SP_APPPRINCIPALID -Value '00000003-0000-0ff1-ce00-000000000000' | Out-Null
New-Variable -Option Constant -Name ACS_APPPRINCIPALID -Value '00000001-0000-0000-c000-000000000000' | Out-Null
New-Variable -Option Constant -Name ACS_APPPROXY_NAME -Value ACS
New-Variable -Option Constant -Name SPO_MANAGEMENT_APPPROXY_NAME -Value 'SPO Add-in Management Proxy'
New-Variable -Option Constant -Name ACS_STS_NAME -Value ACS-STS
New-Variable -Option Constant -Name AAD_METADATAEP_FSTRING -Value 'https://accounts.accesscontrol.windows.net/{0}/metadata/json/1'
New-Variable -Option Constant -Name SP_METADATAEP_FSTRING -Value '{0}/_layouts/15/metadata/json/1'
#Get the default SPWeb from the on-premises farm if no $SharePointWeb parameter is specified.
if ([String]::IsNullOrEmpty($SharePointWeb)) {
$SharePointWeb = Get-SPSite | Select-Object -First 1 | Get-SPWeb | Select-Object -First 1 | % Url
}
#Configure the realm ID for local farm so that it matches the AAD realm.
$ACSMetadataEndpoint = $AAD_METADATAEP_FSTRING -f $AADDomain
$ACSMetadata = Invoke-RestMethod -Uri $ACSMetadataEndpoint
$AADRealmId = $ACSMetadata.realm
Set-SPAuthenticationRealm -ServiceContext $SharePointWeb -Realm $AADRealmId
$LocalSTS = Get-SPSecurityTokenServiceConfig
$LocalSTS.NameIdentifier = '{0}@{1}' -f $SP_APPPRINCIPALID,$AADRealmId
$LocalSTS.Update()
#Allow connections over HTTP if the switch is specified.
if ($AllowOverHttp.IsPresent -and $AllowOverHttp -eq $True) {
$serviceConfig = Get-SPSecurityTokenServiceConfig
$serviceConfig.AllowOAuthOverHttp = $true
$serviceConfig.AllowMetadataOverHttp = $true
$serviceConfig.Update()
}
#Step 1: Set up the ACS proxy in the on-premises SharePoint farm. Remove the existing ACS proxy
#if the switch is specified.
if ($RemoveExistingACS.IsPresent -and $RemoveExistingACS -eq $True) {
Get-SPServiceApplicationProxy | ? DisplayName -EQ $ACS_APPPROXY_NAME | Remove-SPServiceApplicationProxy -RemoveData -Confirm:$false
}
if (-not (Get-SPServiceApplicationProxy | ? DisplayName -EQ $ACS_APPPROXY_NAME)) {
$AzureACSProxy = New-SPAzureAccessControlServiceApplicationProxy -Name $ACS_APPPROXY_NAME -MetadataServiceEndpointUri $ACSMetadataEndpoint -DefaultProxyGroup
}
#Remove the existing security token service if the switch is specified.
if ($RemoveExistingSTS.IsPresent) {
Get-SPTrustedSecurityTokenIssuer | ? Name -EQ $ACS_STS_NAME | Remove-SPTrustedSecurityTokenIssuer -Confirm:$false
}
if (-not (Get-SPTrustedSecurityTokenIssuer | ? DisplayName -EQ $ACS_STS_NAME)) {
$AzureACSSTS = New-SPTrustedSecurityTokenIssuer -Name $ACS_STS_NAME -IsTrustBroker -MetadataEndPoint $ACSMetadataEndpoint
}
#Update the ACS Proxy for OAuth authentication.
$ACSProxy = Get-SPServiceApplicationProxy | ? Name -EQ $ACS_APPPROXY_NAME
$ACSProxy.DiscoveryConfiguration.SecurityTokenServiceName = $ACS_APPPRINCIPALID
$ACSProxy.Update()
#Retrieve the local STS signing key from JSON metadata.
$SPMetadata = Invoke-RestMethod -Uri ($SP_METADATAEP_FSTRING -f $SharePointWeb)
$SPSigningKey = $SPMetadata.keys | ? usage -EQ "Signing" | % keyValue
$CertValue = $SPSigningKey.value
#Connect to Office 365.
Connect-MsolService -Credential $O365Credentials
#Remove existing connection to an Office 365 SharePoint site if the switch is specified.
if ($RemoveExistingAADCredentials.IsPresent -and $RemoveExistingAADCredentials -eq $true) {
$msolserviceprincipal = Get-MsolServicePrincipal -AppPrincipalId $SP_APPPRINCIPALID
[Guid[]] $ExistingKeyIds = Get-MsolServicePrincipalCredential -ObjectId $msolserviceprincipal.ObjectId -ReturnKeyValues $false | % {if ($_.Type -ne "Other") {$_.KeyId}}
Remove-MsolServicePrincipalCredential -AppPrincipalId $SP_APPPRINCIPALID -KeyIds $ExistingKeyIds
}
#Step 2: Upload the local STS signing certificate
New-MsolServicePrincipalCredential -AppPrincipalId $SP_APPPRINCIPALID -Type Asymmetric -Value $CertValue -Usage Verify
#Step 3: Add the service principal name of the local web application, if necessary.
$indexHostName = $SharePointWeb.IndexOf('://') + 3
$HostName = $SharePointWeb.Substring($indexHostName)
$NewSPN = '{0}/{1}' -f $SP_APPPRINCIPALID, $HostName
$SPAppPrincipal = Get-MsolServicePrincipal -AppPrincipalId $SP_APPPRINCIPALID
if ($SPAppPrincipal.ServicePrincipalNames -notcontains $NewSPN) {
$SPAppPrincipal.ServicePrincipalNames.Add($NewSPN)
Set-MsolServicePrincipal -AppPrincipalId $SPAppPrincipal.AppPrincipalId -ServicePrincipalNames $SPAppPrincipal.ServicePrincipalNames
}
#Remove the existing SharePoint Online proxy if the switch is specified.
if ($RemoveExistingSPOProxy.IsPresent -and $RemoveExistingSPOProxy -eq $True) {
Get-SPServiceApplicationProxy | ? DisplayName -EQ $SPO_MANAGEMENT_APPPROXY_NAME | Remove-SPServiceApplicationProxy -RemoveData -Confirm:$false
}
#Step 4: Add the SharePoint Online proxy
if (-not (Get-SPServiceApplicationProxy | ? DisplayName -EQ $SPO_MANAGEMENT_APPPROXY_NAME)) {
$spoproxy = New-SPOnlineApplicationPrincipalManagementServiceApplicationProxy -Name $SPO_MANAGEMENT_APPPROXY_NAME -OnlineTenantUri $SharePointOnlineUrl -DefaultProxyGroup
}
}
针对 Office 应用商店配置加载项和 SharePoint Web 应用程序
如果场管理员想让用户能够从 Office 应用商店安装使用 ACS 的提供程序托管的加载项,则有一个可供场管理员在生产环境中采用的可选配置步骤。 (除非计划从 SharePoint 开发环境中的应用商店安装使用 ACS 的加载项,否则在该环境中毫无用处。)以下 cmdlet 能够实现此目的。 可以将此代码添加到上述函数。
New-SPMarketplaceWebServiceApplicationProxy -Name "ApplicationIdentityDataWebServiceProxy" -ServiceEndpointUri "https://oauth.sellerdashboard.microsoft.com/ApplicationIdentityDataWebService.svc" -DefaultProxyGroup
对于生产 SharePoint Web 应用程序而言,在完成以上配置步骤后,最佳做法是激活“需要可访问的面向 Internet 的终结点的加载项”功能。 (请参阅下面的说明。)此功能实际上不起任何作用。 它只是作为一个标志,告知 Office 应用商店:使用 ACS 的提供程序托管的加载项可以在 SharePoint Web 应用程序中的网站上安装。
此系统可能会影响 SharePoint 加载项的加载项清单。 如果计划通过应用商店出售你的加载项,最佳做法是将以下 AppPrerequisite 添加到该加载项清单的 AppPrerequisites 部分:
<AppPrerequisite Type="Feature" ID="{7877bbf6-30f5-4f58-99d9-a0cc787c1300}" />
先决条件的作用是,当用户正在从本地 SharePoint 场浏览应用商店时,如果父 SharePoint Web 应用程序未启用“需要可访问的面向 Internet 的终结点的加载项”功能,加载项将为灰显且不能安装。 这将确保在客户将你的加载项安装到本地 SharePoint 网站,并发现无法正常使用时,你将不会收到客户的投诉。
有两种方法可以启用该功能。 第一种方法是在任意 SharePoint 服务器上运行以下 PowerShell cmdlet(可添加到上述函数的末尾处):
Enable-SPFeature -identity "7877bbf6-30f5-4f58-99d9-a0cc787c1300" -Url http://domain_of_the_SharePoint_web_application
另一种启用此功能的方法是在管理中心执行下列步骤:
在“SharePoint 管理中心”中,转到“应用程序管理”>“管理 Web 应用程序”。
在“管理 Web 应用程序”页上,选择要更改的 Web 应用程序。
在功能区上选择“管理功能”。
在功能列表中的“需要可访问的面向 Internet 的终结点的加载项”旁边,选择“激活”。
选择“确定”。
在场中配置其他 SharePoint Web 应用程序
如果您的 SharePoint 场中有其他 Web 应用程序,并且您希望在场中运行使用 ACS 信任的提供程序托管的外接程序,则可以使用此 Windows PowerShell 脚本(在 SharePoint Management Shell中)将它们添加到服务主体名称集合中。
$SPAppPrincipal = Get-MsolServicePrincipal -AppPrincipalId 00000003-0000-0ff1-ce00-000000000000
$id = "00000003-0000-0ff1-ce00-000000000000/"
Get-SPWebApplication | ForEach-Object {
$hostName = $_.Url.substring($_.Url.indexof("//") + 2)
$hostName = $hostName.Remove($hostName.Length - 1, 1)
$NewSPN = $id + $hostName
Write-Host "Adding SPN for" $NewSPN
if ($SPAppPrincipal.ServicePrincipalNames -notcontains $NewSPN) {
$SPAppPrincipal.ServicePrincipalNames.Add($NewSPN)
Set-MsolServicePrincipal -AppPrincipalId $SPAppPrincipal.AppPrincipalId -ServicePrincipalNames $SPAppPrincipal.ServicePrincipalNames
}
}