在
<appSettings>
部分,Visual Studio 的 Office 开发人员工具已添加 SharePoint 加载项的
ClientID
和
ClientSecret
元素。 (如果 ASP.NET 应用程序访问 SharePoint,则这些在 Azure ACS 授权系统中使用。对于后续示例,可以忽略它们,但不要删除它们。即使加载项未访问 SharePoint 数据,提供程序托管的 SharePoint 外接程序也需要它们。每次在 Visual Studio 中选择 F5 时,其值都会更改。)
将以下两个元素添加到此部分。 应用程序使用这两个元素来向 Azure AD 进行身份验证。 (请记住,在基于 OAuth 的身份验证和授权系统中,应用程序和用户都是安全主体。)
<add key="ida:ClientID" value="" />
<add key="ida:ClientKey" value="" />
插入在之前的过程中从 Azure AD 目录保存的客户端 ID,作为 ida:ClientID 密钥的值。 在复制过程中,完全保留大小写和标点符号,注意不要在值的开头或结尾包含空格字符。 对于 ida:ClientKey 密钥,请使用从目录中保存的 密钥 。 同样,请注意不要引入任何空格字符或以任何方式改变值。 <appSettings>
部分现在应如下所示(ClientId 值可能具有 GUID 或空字符串):
<appSettings>
<add key="ClientId" value="" />
<add key="ClientSecret" value="LypZu2yVajlHfPLRn5J2hBrwCk5aBOHxE4PtKCjIQkk=" />
<add key="ida:ClientID" value="4da99afe-08b5-4bce-bc66-5356482ec2df" />
<add key="ida:ClientKey" value="URwh/oiPay/b5jJWYHgkVdoE/x7gq3zZdtcl/cG14ss=" />
</appSettings>
Azure AD 可通过你用于注册应用程序的“localhost”URL 定位到该应用程序。 客户端 ID 和客户端密钥与此标识相关联。 在准备将应用程序暂存到 Azure 网站时,将使用一个新的 URL 重新注册它。
同样在“appSettings”部分,添加 Authority 密钥,然后将其值设置为组织帐户的 Office 365 域 (some_domain.onmicrosoft.com)。 在下面的示例中,组织帐户为 Bob@<O365_domain>.onmicrosoft.com
,因此颁发机构是 <O365_domain>.onmicrosoft.com
。
<add key="Authority" value="<O365_domain>.onmicrosoft.com" />
同样在“appSettings”部分,添加 AppRedirectUrl 密钥,并将其值设置为在 ASP.NET 加载项从 Azure AD 中获取授权代码后,用户浏览器应重定向到的页面。 通常情况下,这是调用 Azure AD 时用户位于的页面。 在下面的示例中,使用 SSL URL 值及其所附加的“/Pages/Default.aspx”,如下所示。(这是需要为暂存更改的另一个值):
<add key="AppRedirectUrl" value="https://localhost:44322/Pages/Default.aspx" />
仍在 appSettings 部分中,添加 ResourceUrl 密钥并将其值设置为 SAP Gateway for Microsoft 的应用 ID URI (而不是 ASP.NET 应用程序) 的应用 ID URI。 从 SAP Gateway for Microsoft 管理员处获取此值。 示例如下。
<add key="ResourceUrl" value="http://<SAP_gateway_domain>.cloudapp.net/" />
<appSettings>
部分现在应该如下所示:
<appSettings>
<add key="ClientId" value="06af1059-8916-4851-a271-2705e8cf53c6" />
<add key="ClientSecret" value="LypZu2yVajlHfPLRn5J2hBrwCk5aBOHxE4PtKCjIQkk=" />
<add key="ida:ClientID" value="4da99afe-08b5-4bce-bc66-5356482ec2df" />
<add key="ida:ClientKey" value="URwh/oiPay/b5jJWYHgkVdoE/x7gq3zZdtcl/cG14ss=" />
<add key="Authority" value="<O365_domain>.onmicrosoft.com" />
<add key="AppRedirectUrl" value="https://localhost:44322/Pages/Default.aspx" />
<add key="ResourceUrl" value="http://<SAP_gateway_domain>.cloudapp.net/" />
</appSettings>
保存并关闭 web.config 文件。
在运行 Visual Studio 调试器 (F5) 时,请勿将 web.config 文件保持打开状态。 每次选择 F5 时,Visual Studio 的 Office 开发人员工具都会更改 ClientId 值(而非 ida:ClientID)。 如果 web.config 文件处于打开状态,则你会收到重新加载此文件的提示并做出响应,然后才能执行调试。
添加帮助程序类以进行 Azure AD 身份验证
右键单击 ASP.NET 项目,并使用 Visual Studio 项目添加进程向名为 AADAuthHelper.cs 的项目添加新的类文件。
向文件添加以下 using 语句。
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Configuration;
using System.Web.UI;
将访问关键字从 public 更改为 internal,并将 static 关键字添加到类声明。
internal static class AADAuthHelper
将下列字段添加到类 这些字段存储 ASP.NET 应用程序用于获取 Azure AD 中访问令牌的信息。
private static readonly string _authority = ConfigurationManager.AppSettings["Authority"];
private static readonly string _appRedirectUrl = ConfigurationManager.AppSettings["AppRedirectUrl"];
private static readonly string _resourceUrl = ConfigurationManager.AppSettings["ResourceUrl"];
private static readonly string _clientId = ConfigurationManager.AppSettings["ida:ClientID"];
private static readonly ClientCredential _clientCredential = new ClientCredential(
ConfigurationManager.AppSettings["ida:ClientID"],
ConfigurationManager.AppSettings["ida:ClientKey"]);
private static readonly AuthenticationContext _authenticationContext =
new AuthenticationContext("https://login.windows.net/common/" +
ConfigurationManager.AppSettings["Authority"]);
将以下属性添加到类。 该属性保留指向 Azure AD 登录屏幕的 URL。
private static string AuthorizeUrl
return string.Format("https://login.windows.net/{0}/oauth2/authorize?response_type=code&redirect_uri={1}&client_id={2}&state={3}",
_authority,
_appRedirectUrl,
_clientId,
Guid.NewGuid().ToString());
将下列属性添加到类。 这些属性缓存访问令牌和刷新令牌并检查它们的有效性。
public static Tuple<string, DateTimeOffset> AccessToken
get {
return HttpContext.Current.Session["AccessTokenWithExpireTime-" + _resourceUrl]
as Tuple<string, DateTimeOffset>;
set { HttpContext.Current.Session["AccessTokenWithExpireTime-" + _resourceUrl] = value; }
private static bool IsAccessTokenValid
return AccessToken != null
&& !string.IsNullOrEmpty(AccessToken.Item1)
&& AccessToken.Item2 > DateTimeOffset.UtcNow;
private static string RefreshToken
get { return HttpContext.Current.Session["RefreshToken" + _resourceUrl] as string; }
set { HttpContext.Current.Session["RefreshToken-" + _resourceUrl] = value; }
private static bool IsRefreshTokenValid
get { return !string.IsNullOrEmpty(RefreshToken); }
将下列方法添加到类。 这些代码用于检查授权代码的有效性,并使用身份验证代码或刷新令牌从 Azure AD 获取访问令牌。
private static bool IsAuthorizationCodeNotNull(string authCode)
return !string.IsNullOrEmpty(authCode);
private static Tuple<Tuple<string,DateTimeOffset>,string> AcquireTokensUsingAuthCode(string authCode)
var authResult = _authenticationContext.AcquireTokenByAuthorizationCode(
authCode,
new Uri(_appRedirectUrl),
_clientCredential,
_resourceUrl);
return new Tuple<Tuple<string, DateTimeOffset>, string>(
new Tuple<string, DateTimeOffset>(authResult.AccessToken, authResult.ExpiresOn),
authResult.RefreshToken);
private static Tuple<string, DateTimeOffset> RenewAccessTokenUsingRefreshToken()
var authResult = _authenticationContext.AcquireTokenByRefreshToken(
RefreshToken,
_clientCredential.OwnerId,
_clientCredential,
_resourceUrl);
return new Tuple<string, DateTimeOffset>(authResult.AccessToken, authResult.ExpiresOn);
将以下方法添加到类。 此方法从后台的 ASP.NET 代码调用以获取有效的访问令牌,然后执行调用,通过 SAP Gateway for Microsoft 获取 SAP 数据。
internal static void EnsureValidAccessToken(Page page)
if (IsAccessTokenValid)
return;
else if (IsRefreshTokenValid)
AccessToken = RenewAccessTokenUsingRefreshToken();
return;
else if (IsAuthorizationCodeNotNull(page.Request.QueryString["code"]))
Tuple<Tuple<string, DateTimeOffset>, string> tokens = null;
tokens = AcquireTokensUsingAuthCode(page.Request.QueryString["code"]);
catch
page.Response.Redirect(AuthorizeUrl);
AccessToken = tokens.Item1;
RefreshToken = tokens.Item2;
return;
page.Response.Redirect(AuthorizeUrl);
类 AADAuthHelper
只有最小的错误处理。 要实现生产质量的可靠 SharePoint 加载项,请增加更多错误处理,如此 MSDN 节点中所述:使用 OAuth 2.0 和 Azure Active Directory 授权访问 Web 应用程序。
创建数据模型类
创建一个或多个类,对加载项从 SAP 中获取的数据进行建模。 在下面的示例中,只有一个数据模型类。 右键单击 ASP.NET 项目,并使用 Visual Studio 项目添加进程向名为 Automobile.cs 的项目添加新的类文件。
将以下代码添加到类的正文:
public string Price;
public string Brand;
public string Model;
public int Year;
public string Engine;
public int MaxPower;
public string BodyStyle;
public string Transmission;
通过 SAP Gateway for Microsoft 在后台添加代码以获取 SAP 中的数据
打开 Default.aspx.cs 文件,并添加以下 using 语句。
using System.Net;
using Newtonsoft.Json.Linq;
将 const 声明添加到 Default 类,其值为外接程序将访问的 SAP OData 终结点的基 URL。 示例如下:
private const string SAP_ODATA_URL = @"https://<SAP_gateway_domain>.cloudapp.net:8081/perf/sap/opu/odata/sap/ZCAR_POC_SRV/";
适用于 Visual Studio 的 Office 开发人员工具添加了 Page_PreInit 方法和 Page_Load 方法。 注释掉 Page_Load 方法中的代码,并注释掉整个 Page_Init 方法。 此代码未在此示例中使用。 (如果 SharePoint 加载项要访问 SharePoint,应还原此代码。 请参阅向 ASP.NET 应用程序添加 SharePoint 访问权限(可选)。)
将以下行添加到 Page_Load 方法最前面。 这将简化调试过程,因为 ASP.NET 应用程序使用 SSL (HTTPS) 与 SAP Gateway for Microsoft 进行通信,但是“localhost:port”服务器未配置为信任 SAP Gateway for Microsoft 的证书。 如果没有此代码行,在 Default.aspx 打开之前,你将收到证书无效的警告。 某些浏览器允许单击跳过此错误,但是有些浏览器根本不允许打开 Default.aspx。
ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, errors) => true;
当您准备好将 ASP.NET 应用程序部署到暂存环境之后,删除此行。 请参阅修改外接程序并将其暂存到 Azure 和 Office 365。
将以下代码添加到 Page_Load 方法。 传递给 方法的 GetSAPData
字符串是 OData 查询。
if (!IsPostBack)
GetSAPData("DataCollection?$top=3");
将以下方法添加到 Default 类。 此方法首先确保访问令牌的缓存具有从 Azure AD 获取的有效访问令牌。 然后创建包含访问令牌的 HTTP GET 请求并将其发送到 SAP OData 终结点。 结果是作为 JSON 对象返回,已转换为 .NET List 对象。 项目的三个属性用于绑定到 DataListView 的阵列。
private void GetSAPData(string oDataQuery)
AADAuthHelper.EnsureValidAccessToken(this);
using (WebClient client = new WebClient())
client.Headers[HttpRequestHeader.Accept] = "application/json";
client.Headers[HttpRequestHeader.Authorization] = "Bearer " + AADAuthHelper.AccessToken.Item1;
var jsonString = client.DownloadString(SAP_ODATA_URL + oDataQuery);
var jsonValue = JObject.Parse(jsonString)["d"]["results"];
var dataCol = jsonValue.ToObject<List<Automobile>>();
var dataList = dataCol.Select((item) => {
return item.Brand + " " + item.Model + " " + item.Price;
}).ToArray();
DataListView.DataSource = dataList;
DataListView.DataBind();
创建用户界面
打开 Default.aspx 文件,并将以下标记添加到页面的 form:
<h3>Data from SAP via SAP Gateway for Microsoft</h3>
<asp:ListView runat="server" ID="DataListView">
<ItemTemplate>
<tr runat="server">
<td runat="server">
<asp:Label ID="DataLabel" runat="server"
Text="<%# Container.DataItem.ToString()%>" /><br />
</ItemTemplate>
</asp:ListView>
可以选择通过 SharePoint Chrome 控件和主机 SharePoint 网站的样式表为网页设置 SharePoint 页面外观。
在 Visual Studio 中使用 F5 测试加载项
在 Visual Studio 中,选择 F5。
首次使用 F5 时,可能会提示你登录到正在使用的开发人员网站。 使用网站管理员凭据。 在下面的示例中为 Bob@<O365_domain>.onmicrosoft.com
。
首次使用 F5 时,将提示你授予对加载项的权限。 选择“信任它”。
获取访问令牌时的短暂延迟后,Default.aspx 页面将打开。 确认 SAP 数据显示。
向 ASP.NET 应用程序添加 SharePoint 访问权限(可选)
当然,SharePoint 加载项不一定要仅将 SAP 数据显示在从 SharePoint 启动的网页中。 它还可以创建、读取、更新和删除 (CRUD) SharePoint 数据。 后台代码可以使用 SharePoint 客户端对象模型 (CSOM) 或 SharePoint 的 REST API 执行此操作。 CSOM 部署为一对程序集,Visual Studio 的 Office 开发人员工具会将其自动包含在 ASP.NET 项目中,并在 Visual Studio 中将其设置为 Copy Local,这样它们就可以包含在 ASP.NET 应用程序包中。
有关使用 CSOM 的信息,请首先阅读使用 SharePoint 客户端库代码完成基本操作。 有关使用 REST API 的信息,请从 了解和使用 SharePoint REST 接口开始。
无论是使用 CSOM 还是 REST API 访问 SharePoint,ASP.NET 应用程序都必须获得 SharePoint 的访问令牌,就像必须获取 SAP Gateway for Microsoft 的访问令牌一样。 请参阅本文前面所述的了解对 SAP Gateway for Microsoft 和 SharePoint 的身份验证及授权
下面的过程提供了关于如何执行此操作的基本指导,但建议首先阅读以下文章:
开始创建提供程序托管的 SharePoint 加载项
SharePoint 外接程序的授权和身份验证
SharePoint 外接程序的三种授权系统
创建使用低信任授权的 SharePoint 外接程序
SharePoint 加载项的上下文标记 OAuth 流
向 ASP.NET 应用程序添加 SharePoint 访问权限
打开 Default.aspx.cs 文件并取消注释 Page_PreInit
方法。 此外,取消注释 Office Developer Tools for Visual Studio 添加到 方法的代码 Page_Load
。
如果 SharePoint 加载项要访问 SharePoint 数据,那么当加载项在 SharePoint 中启动时,必须将已执行 POST 操作的 SharePoint 上下文标记缓存到 Default.aspx 页面。 这是为了确保当浏览器按照 Azure AD 身份验证重定向时,SharePoint 上下文标记不会丢失。 (对于如何缓存此上下文,有几个选项。)Visual Studio 的 Office 开发人员工具将 SharePointContext.cs 文件添加到执行大部分工作的 ASP.NET 项目。 若要使用会话缓存,只需在 if (!IsPostBack)
块内,在调用 SAP Gateway for Microsoft 的代码前面添加以下代码。
if (HttpContext.Current.Session["SharePointContext"] == null)
HttpContext.Current.Session["SharePointContext"]
= SharePointContextProvider.Current.GetSharePointContext(Context);
SharePointContext.cs 文件调用 Office Developer Tools for Visual Studio 添加到项目的另一个文件:TokenHelper.cs。 此文件提供获取和使用 SharePoint 访问令牌所需的大部分代码。 但是,它不提供续订已过期访问令牌或已过期的刷新令牌的任何代码。 它也不包含任何令牌缓存代码。 对于生产质量 SharePoint 外接程序,需要添加此类代码。 例如前一步中的缓存逻辑。 您的代码还应该缓存访问令牌并重复使用,直至其过期。 当访问令牌过期时,您的代码应使用刷新令牌获取新的访问令牌。
使用 CSOM 或 REST 向 SharePoint 添加数据调用。 下面的示例修改 Visual Studio 的 Office 开发人员工具添加到 Page_Load 方法的 CSOM 代码。 在本示例中,代码已移至单独的方法中,并开始检索已缓存的上下文标记。
private void GetSharePointTitle()
var spContext = HttpContext.Current.Session["SharePointContext"] as SharePointContext;
using (var clientContext = spContext.CreateUserClientContextForSPHost())
clientContext.Load(clientContext.Web, web => web.Title);
clientContext.ExecuteQuery();
SharePointTitle.Text = "SharePoint website title is: " + clientContext.Web.Title;
添加 UI 元素以呈现 SharePoint 数据。 下面显示了在前一方法中引用的 HTML 控件:
<h3>SharePoint title</h3>
<asp:Label ID="SharePointTitle" runat="server"></asp:Label><br />
调试 SharePoint 加载项时,每次在 Visual Studio 中选择 F5 时,Visual Studio 的 Office 开发人员工具都会将其在 Azure ACS 中重新注册。 在暂存 SharePoint 加载项时,必须为其提供长期注册。 请参阅修改加载项并将其暂存到 Azure 和 Office 365。
修改加载项并将其暂存到 Azure 和 Office 365
在 Visual Studio 中使用 F5 调试完 SharePoint 加载项之后,需要将 ASP.NET 应用程序部署到实际的 Azure 网站。
创建 Azure 网站
在 Microsoft Azure 门户中,在左侧导航栏上打开“网站”。
在页面底部选择“新建”,在“新建”对话框中选择“网站” |“快速创建”。
输入域名,然后选择“创建网站”。 创建新网站 URL 的副本。 其格式 为 my_domain.azurewebsites.net。
修改应用程序中的代码和标记
在 Visual Studio 中,从 Default.aspx.cs 文件中删除行ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, errors) => true;
。
打开 ASP.NET 项目的web.config 文件,并将 部分中键appSettings
值的AppRedirectUrl
域部分更改为 Azure 网站的域。 例如,将 <add key="AppRedirectUrl" value="https://localhost:44322/Pages/Default.aspx" />
更改为 <add key="AppRedirectUrl" value="https://my_domain.azurewebsites.net/Pages/Default.aspx" />
。
在 SharePoint 外接程序项目中右键单击 AppManifest.xml 文件,然后选择“ 查看代码”。
在 值中 StartPage
,将 字符串 ~remoteAppUrl
替换为 Azure 网站的完整域(包括协议);例如 https://my_domain.azurewebsites.net
。 现在,整个StartPage
值通常应https://my_domain.azurewebsites.net/Pages/Default.aspx
(,StartPage
该值与 web.config 文件中键的值AppRedirectUrl
) 完全相同。
修改 Azure AD 注册并在 ACS 中注册加载项
使用 Azure 管理员帐户登录到 Azure 门户。
选择左侧的“Active Directory”。
选择目录。
选择“应用程序”(位于顶部导航栏上)。
打开您创建的应用程序。 在下面的示例中,为“ContosoAutomobileCollection”。
对于以下各值,将值的“localhost:port”部分更改为新 Azure 网站的域:
登录 URL
应用 ID URI
回复 URL
例如,如果应用 ID URI 为 https://localhost:44304/ContosoAutomobileCollection
,将其更改为 https://<my_domain>.azurewebsites.net/ContosoAutomobileCollection
。
选择屏幕底部的“保存”。
在 Azure ACS 中注册加载项。 即使加载项不访问 SharePoint 也不使用 ACS 中的令牌,也必须执行此操作,这是因为此过程也会在 Office 365 订阅的加载项管理服务注册加载项,这是必要条件。 (称为“加载项管理服务”,因为 SharePoint 加载项最初称为“SharePoint 相关应用程序”。)
可以在 Office 365 订阅中任何 SharePoint 网站的 AppRegNew.aspx 页面上执行注册。 有关详细信息,请参阅注册 SharePoint 加载项。
作为此过程的一部分,需要获取新的客户端 ID 和客户端密码。 将这些值插入 ClientId(不是 ida:ClientID)和 ClientSecret 密钥的 web.config 中。
进行此更改后,不论出于何种原因选择 F5,Visual Studio 的 Office 开发人员工具都会覆盖一个或两个值。 因此,应记录在 AppRegNew.aspx 中获取的值,并始终在发布 ASP.NET 应用程序之前确认 web.config 中的值正确无误。
将 ASP.NET 应用程序发布到 Azure 并将加载项安装到 SharePoint
有几种方法可将 ASP.NET 应用程序发布到 Azure 网站。 有关详细信息,请参阅针对 Azure 应用服务的本地 Git 部署。
在 Visual Studio 中,右键单击 SharePoint 加载项项目,然后选择“打包”。 在打开的“发布加载项”页上,选择“打包加载项”。 文件资源管理器将打开到包含加载项包的文件夹。
以全局管理员身份登录到 Office 365,导航到组织加载项目录网站集。 (如果没有,请创建它。请参阅 使用外接程序目录使自定义业务加载项可用于 SharePoint Online 环境。)
将加载项包上传到加载项目录。
导航到订阅中任何网站的“网站内容”页,并选择“添加加载项”。
在“加载项”页上,滚动到“可以添加的加载项”部分,并选择加载项图标。
安装加载项后,在“网站内容”页上选择其图标启动加载项。
有关安装 SharePoint 加载项的详细信息,请参阅部署和安装 SharePoint 加载项:方法和选项。
将加载项部署到生产环境
完成所有测试后,可以在生产环境中部署加载项。 这可能需要进行一些更改。
如果 ASP.NET 应用程序的生产域与暂存域不同,则必须更改 AppRedirectUrl
web.config 中的值和 StartPage
AppManifest.xml 文件中的值,然后重新打包 SharePoint 外接程序。 请参阅本文前面所述的过程修改应用程序中的代码和标记。
域更改还需要编辑 Azure AD 中的加载项注册。 请参阅本文前面所述的过程修改 Azure AD 注册并在 ACS 中注册加载项。
域更改还需要在 ACS(和订阅的加载项管理服务)中按照此相同过程中所述的方式重新注册加载项。 (无法 编辑 使用 ACS.) 但是,无需在 AppRegNew.aspx 页上生成新的客户端 ID 或客户端密码。 可以将原始值从 ClientId
web.config的 (“非 ida:ClientID
) 和 ClientSecret
密钥 ”复制到 AppRegNew 窗体中。 如果确实生成了新值,请确保将新值复制到 web.config中的键。
开发 SharePoint 加载项