【问题标题】:Error 403 during POST on SharePoint 2013 REST API [on premise]在 SharePoint 2013 REST API [本地] 上发布期间出现错误 403
【发布时间】:2018-10-17 05:59:59
【问题描述】:

我很难理解为什么在使用 httpclient 创建列表项时出现错误 403。我完全控制了列表,但我收到了 403,这非常令人沮丧。我经历了很多解决方案,但没有一个对我有用。

如果我使用对列表的 ajax 调用创建 HTML 页面,我可以从浏览器创建列表项,但是用 c# 编写的相同代码会引发错误 403。

这是我的 C# 测试代码,它抛出 403,响应为

{"error":{"code":"-2130575251, Microsoft.SharePoint.SPException","message":{"lang":"en-US","value":"The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again."}}}

            NetworkCredential cred = new NetworkCredential(username, password);
            HttpClient client = new HttpClient(new HttpClientHandler() { Credentials = cred })
            {
                BaseAddress = new Uri(URL)
            };
            string cmd = "_api/contextinfo";

            client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
            client.DefaultRequestHeaders.Add("ContentType", "application/json");

            StringContent httpContent = new StringContent("");

            var clientresponse = await client.PostAsync(cmd, httpContent);

            if (clientresponse.IsSuccessStatusCode)
            {
                string formdigest = await clientresponse.Content.ReadAsStringAsync();
                JToken t = JToken.Parse(formdigest);
                string digest = t["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
                string[] digestArray = digest.Split(',');

                NetworkCredential cred2 = new NetworkCredential(username, password);
                HttpClient client2 = new HttpClient(new HttpClientHandler() { Credentials = cred2 })
                {
                    BaseAddress = new Uri(URL)
                };
                client2.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
                client2.DefaultRequestHeaders.Add("ContentType", "application/json");
                client2.DefaultRequestHeaders.Add("X-HTTP-Method", "POST");
                client2.DefaultRequestHeaders.Add("X-RequestDigest", digestArray[0].ToString());


                string path = SendShipments.ListPath + "_api/Web/Lists/getbytitle("Test")/items";

                string content_Post = "{__metadata:{'type':'SP.Data.TestListItem'},Title:'Test'}";


                var httpContent_Post = new StringContent(content_Post, Encoding.UTF8, "application/json");

                var clientresponse2 = await client2.PostAsync(path, httpContent_Post);

这是我的 ajax 代码,按预期工作

<script>
    $.ajax({
        url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('Test')/items",
        type: "POST",
        headers: {
            "accept": "application/json;odata=verbose",
            "X-RequestDigest": $("#__REQUESTDIGEST").val(),
            "content-Type": "application/json;odata=verbose"
        },
        data: "{__metadata:{'type':'SP.Data.TestListItem'},Title:'Test'}",
        /*where Title is column name and you can add more columns by splitting with ,*/
        success: function (data) {
            console.log(data.d.results);
        },
        error: function (error) {
            alert(JSON.stringify(error));
        }
    });
</script>

我尝试添加HttpContext.Current.Items["FormDigestValidated"] = true;,但没有成功。

请指教。谢谢

【问题讨论】:

  • 为了让 sharepoint api 正常工作,我必须在租户中使用应用程序权限(未委托,即 ui)注册应用程序,并为应用程序上传 X509 证书。然后我需要使用与证书中的公钥关联的私钥来签署 JWT 以获得访问令牌。

标签: c# rest sharepoint-2013 dotnet-httpclient


【解决方案1】:

403 错误很可能是由于无效的FormDigest 值而发生的。 根据这些行:

string digest = t["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
string[] digestArray = digest.Split(',');

和

client2.DefaultRequestHeaders.Add("X-RequestDigest", digestArray[0].ToString());

摘要值在没有时间戳部分的情况下传递,这使得表单摘要值无效,整个FormDigestValue属性需要作为X-RequestDigest标头传递而不是作为如下所示:

var formDigest = GetFormDigest(client);

var message = new HttpRequestMessage(HttpMethod.Post, "_api/web/webs/add");
message.Headers.Add("Accept", "application/json;odata=verbose");
message.Headers.Add("X-RequestDigest", formDigest);

在哪里

public static string GetFormDigest(HttpClient client)
{
   var message = new HttpRequestMessage(HttpMethod.Post, "_api/contextinfo");
   message.Headers.Add("Accept", "application/json;odata=verbose");
   var result = client.SendAsync(message).Result;
   result.EnsureSuccessStatusCode();
   var content = result.Content.ReadAsStringAsync().Result;
   var json = JToken.Parse(content);
   var formDigest = json["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
   return formDigest;
}

【讨论】:

  • 感谢 Vadim 的解释,但不幸的是,在尝试解决方案后,我遇到了同样的错误。我能够毫无问题地执行 get,但帖子似乎与权限级别的某些内容有关。
  • 确实可能和权限有关,验证了我这边提供的代码,似乎工作正常
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-02
  • 2018-09-15
  • 1970-01-01
  • 2015-07-22
  • 2019-05-08
  • 2014-11-01
  • 1970-01-01
相关资源
最近更新 更多