1

I have a Silverlight 5 app that runs on a SharePoint 2007 site. The Silverlight app gets a bunch of data from SharePoint lists using the Lists.asmx service. The main site is secured using NTLM security and Silverlight is able to successfully call the web services without having to eplicitly set anything to do with authentication. We extended the SharePoint site to a second domain that uses asp.net FormsBasedAuthentication. On this version of the site, the first web service call fails with a 403 Forbidden response and the exception:

System.ServiceModel.CommunicationException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound.

As I understand it, this is a generic message and not the true exception. Well, obviously we need the real exception to have any idea what the problem is. This MSDN page (Creating and Handling Faults in Silverlight) offers two solutions to getting the real exception.

The first is to modify your WCF service to return an alternate HTTP status code. This doesn't work because for one, it is not a WCF service, it's an .asmx web service so I can't add the suggested WCF behavior to modify the status code. Second, it's SharePoint's service so I can't do much to modify it anyway. Could I modify IIS to achieve an equivalent solution somehow?

The second solution is to register an alternative HTTP stack in the Silverlight application. I tried this out and found out the "real" exception was an authentication exception. So I went down dead ends trying to figure out out to get authenticated for about 24 hours only to finally find out that normally, the ASP.NET authentication cookie is passed with the service request, unless you are using the Client HTTP stack. So registering the client HTTP stack allowed me to see real exceptions, but it created its own exception which seems to only be fixed by not using the Client HTTP stack...

I believe have verified with Fiddler that the authentication cookie is being sent when using the default HTTP stack. I don't know if the Lists.asmx service is unable to use it and is giving an authentication error anyway, or if there is some other exception. How can I determine the cause of the "The remote server returned an error: NotFound." exception?

4

1 回答 1

0

好吧,这不是对“我如何确定原因......”这个问题的好答案,但这对我有用。我所做的是在反射器中打开 STSSOAP.dll,即包含 Lists 服务实现的程序集。我复制了相关代码以在我自己的服务中实现我自己的 GetListItems 方法。幸运的是,实际的 Lists.GetListItems 方法代码很少,只是调用了其他 SharePoint 方法,更幸运的是,这些方法和成员都被声明为 public,所以我能够做到这一点。然后我用我在服务器上的版本替换了 Lists.asmx 并附加了调试器以获取一些信息。我发现正在使用我的身份验证 cookie,并且 HttpContext.Current.Session.User.Identity.IsAuthenticated 是真的。所以它知道我已经登录了。

所以我知道 asp.net 认为我已通过身份验证,但 SharePoint 说我没有权限。但是运行应用程序池的服务帐户是 SP 管理员,为什么我没有权限?所以接下来我检查了 SPContext.Current.Web.User; SharePoint 的当前用户。它是空的!换句话说,就 SharePoint 而言,我仍然以匿名用户身份登录,因为我没有使用域用户显式登录,并且匿名用户对我正在访问的列表没有权限或 API 的大部分其余部分。Sean McDonough 对这个问题的回答说明了这一点。

基本上,我需要以提升的权限运行涉及的代码,以使代码在我最初认为它正在运行的 asp.net 服务帐户下运行。如果使用 API,您可以使用 RunWithElevatedPrivileges 委托。但是,如果您正在调用 Web 服务,则不能这样做。我能想到的几个选择是:

  1. 调用使用 Windows 身份验证的基站上的服务。这需要我将凭据嵌入到客户端 Silverlight 应用程序中,这是一种安全威胁,所以我取消了这个。
  2. 实现我自己的 Web 服务来为我获取数据。
    • Web 服务可以使用 SharePoint API 和 RunWithElevatedPrivileges 访问该列表。
    • Web 服务可以调用 Windows 身份验证站点的服务,传递当前凭据或其他嵌入式凭据。

为了便于实施,到目前为止我所做的只是第二个选项下的第二个选项,它正在工作。但是,它很笨重,我可能会更改为我希望也可以使用的选项 1。

于 2013-09-15T13:50:19.207 回答