我正在尝试从远程 SharePoint 站点(不同的 SP Web 应用程序)中的列表中读取值。Web 应用程序使用声明身份验证进行设置,客户端 Web 应用程序 SP 托管帐户配置有 SPN。我相信 Kerberos 和声明设置正确,但我无法访问远程服务器,并且请求导致异常:“远程服务器返回错误:(401)未授权。”
异常发生在行中,ctx.ExecuteQuery();
但它没有捕获异常,if (scope.HasException)
而是由调用代码(在 using{} 块之外)捕获异常。
当我使用 Wireshark 查看远程服务器上的流量时,看起来请求甚至没有到达服务器;就好像 401 发生在 Kerberos 票证交换索赔之前。
这是我的代码:
using (ClientContext ctx = new ClientContext(contextUrl))
{
CredentialCache cc = new CredentialCache();
cc.Add(new Uri(contextUrl), "Kerberos", CredentialCache.DefaultNetworkCredentials);
ctx.Credentials = cc;
ctx.AuthenticationMode = ClientAuthenticationMode.Default;
ExceptionHandlingScope scope = new ExceptionHandlingScope(ctx);
Web ctxWeb = ctx.Web;
List ctxList;
Microsoft.SharePoint.Client.ListItemCollection listItems;
using (scope.StartScope())
{
using (scope.StartTry())
{
ctxList = ctxWeb.Lists.GetByTitle("Reusable Content");
CamlQuery qry = new CamlQuery();
qry.ViewXml = string.Format(ViewQueryByField, "Title", "Text", SharedContentTitle);
listItems = ctxList.GetItems(qry);
ctx.Load(listItems, items => items.Include(
item => item["Title"],
item => item["ReusableHtml"],
item => item["ReusableText"]));
}
using (scope.StartCatch()) { }
using (scope.StartFinally()) { }
}
ctx.ExecuteQuery();
if (scope.HasException)
{
result = string.Format("Error retrieving content<!-- Error Message: {0} | {1} -->", scope.ErrorMessage, contextUrl);
}
if (listItems.Count == 1)
{
Microsoft.SharePoint.Client.ListItem contentItem = listItems[0];
if (SelectedType == SharedContentType.Html)
{
result = contentItem["ReusableHtml"].ToString();
}
else if (SelectedType == SharedContentType.Text)
{
result = contentItem["ReusableText"].ToString();
}
}
}
我意识到在声明中不需要使用 CredentialCache 的部分,但是我能找到的每个示例要么在控制台应用程序中运行,要么在某种客户端应用程序中运行;此代码在常规 ASP.NET UserControl 的代码隐藏中运行。
编辑:我可能应该提到,当远程 URL 是与调用代码(位于 /sites/ 下的网站集中)相同的 Web 应用程序上的根网站集时,上面的代码甚至不起作用 - 换句话说,即使主机名与调用代码相同。
非常感谢您对下一步尝试的任何建议!
麦克风