使用Windows身份验证在Sharepoint 2010中托管自定义REST服务

时间:2013-01-10 22:39:49

标签: .net sharepoint-2010 httpwebrequest windows-authentication wcf-rest

使用Windows身份验证在Sharepoint 2010应用程序中托管此自定义WCF REST服务。

我需要在.NET项目(即控制台项目)中使用这项服务,但凭证的事情让我发疯。我收到了很多400 - bad request401 - unauthorized个回复(取决于我是否包含某些身份验证)。

让我举个例子:

siteUri是SP站点的URL(根/主页),methodUri是返回XML的服务方法的URL。

此外,此站点已通过Windows身份验证。如果我打开浏览器并转到methodUri,我会:

  

请求错误

     

服务器在处理请求时遇到错误。见服务器   记录更多详细信息。

但如果我转到siteUri,则会加载Sharepoint主页,然后我可以再次浏览methodUri,现在我可以正确获得XML响应。

因此,似乎浏览到主页存储了一些cookie,然后在向Web方法发出请求时使用这些cookie。检查Fiddler中的请求我可以确认:

第一个methodUri请求失败,代码为400,请求标头中没有任何Cookie。然后当我浏览主页(siteUri)时,有一些请求/响应似乎是身份验证本身。响应标头包括:

WWW-Authenticate: Negotiate oRswGaADCgEAoxIEEAEAAABDh+CIwTbjqQAAAAA=
Set-Cookie: WSS_KeepSessionAuthenticated={b89d78b2-063d-4ac4-810e-bde4e04a829e}; path=/
Persistent-Auth: true

最后,当再次浏览methodUri时,第一个响应是401 - 未经授权,但在此之后还有另一个请求包括此标题

Cookie: WSS_KeepSessionAuthenticated={b89d78b2-063d-4ac4-810e-bde4e04a829e}
Authorization: Negotiate oXcwdaADCgEBoloEWE5UTE1TU1AAAwAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAABXCiOIGAbEdAAAAD37/i76Dl3jNyK8bIRz57fmjEgQQAQAAAPUXp1AtIpqEAAAAAA==

最终被接受,服务以相应的XML响应。

因此,浏览器足够聪明,可以处理此来回请求/响应,以验证当前的Windows用户。

我的问题是,如何在.NET(3.5或4)中执行此操作但不使用defautl凭据,我需要指定用户名,密码和域名。

我花了5天时间处理这个问题,我可以使用HttpWebRequest中的默认网络凭据使其工作,但是当我手动设置凭据(使用与当前登录用户相同)时,它不起作用。

我发现整件事情不必要过于复杂(谢谢微软),因为我来自一个开源(ruby,python)背景,这种事情很简单。

希望我很清楚,如果您需要任何额外信息,请询问。我愿意为此给予我全部的声誉。

由于

1 个答案:

答案 0 :(得分:0)

好吧,我已经修好了。

这是我最终使用的代码。感谢微软让事情变得如此简单和充分解释。

var siteUri = @"http://sharepoint-site-uri";
var methodUri = @"http://sharepoint-site-uri/namespace/service/method";
string responseXml = null;

var request = (HttpWebRequest)WebRequest.Create(siteUri);
var cc = new CredentialCache { { new Uri(siteUri), "NTLM", new NetworkCredential("user", "pwd", "domain") } };
request.Credentials = cc;

try
{
    // first site request
    var response = (HttpWebResponse)request.GetResponse();
    if (response.StatusCode == HttpStatusCode.OK)
    {
        request = (HttpWebRequest)WebRequest.Create(uri);
        request.CookieContainer = new CookieContainer();

        // copy the authentication cookies from the response
        foreach (Cookie c in response.Cookies)
        {
            request.CookieContainer.Add(c);
        }

        request.ContentType = "application/xml; charset=utf-8";

        // second request, now against the service url
        using (var reader = new StreamReader(request.GetResponse().GetResponseStream()))
        {
            // get the response text
            responseXml = reader.ReadToEnd();
        }
    }
}
catch (Exception e)
{       
   // handle error
}