休息 API 调用删除实体 returns 403 错误

Rest API call for delete entity returns 403 error

以下代码旨在使用给定的分区键和行键从 table 中删除一行。但是我在 fiddler 中关注 request/response。我该如何更正错误?

请求

DELETE https://hireazurestorageacct.table.core.windows.net/mytable(PartitionKey='sample1',%20RowKey='0001')?timeout=20 HTTP/1.1 接受:application/json;odata=nometadata x-ms-date:2017 年 5 月 8 日星期一 17:59:14 GMT x-ms-version: 2015-04-05 Accept-Charset: UTF-8 最大数据服务版本:3.0;NetFx 数据服务版本:1.0;NetFx If-Match: * Content-Type: application/json 授权:SharedKeyLite hireazurestorageacct:3ZHX8lYBec+/9ytiNQb+JV5dpFkLAieuwB5veMkLVUU= 主持人:hireazurestorageacct.table.core.windows.net

回应

HTTP/1.1 403 服务器无法验证请求。确保 Authorization header 的值格式正确,包括签名。 Content-Length: 299 Content-Type: application/json 服务器:Microsoft-HTTPAPI/2.0 x-ms-request-id:a9244f7f-0002-0048-0824-c8afc5000000 日期:2017 年 5 月 8 日星期一 17:59:14 GMT

{"odata.error":{"code":"AuthenticationFailed","message":{"lang":"en-US","value": "Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:a9244f7f-0002-0048-0824-c8afc5000000\nTime:2017-05-08T17:59:14.9335100Z"}}}

代码

public static int DeleteEntity(字符串 storageAccount,字符串 accessKey,字符串 tableName,字符串 partitionkey,字符串 rowkey) { 字符串 uri = $@"https://{storageAccount}.table.core.windows.net/{tableName}(PartitionKey='{partitionkey}', RowKey='{rowkey}')?timeout=20"; 字符串资源 = $@"{table名称}";

        // Web request 
        var request = (HttpWebRequest)WebRequest.Create(uri);
        request.Method = "DELETE";
        request.Accept = "application/json;odata=nometadata";
        request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
        request.Headers.Add("x-ms-version", "2015-04-05");
        request.Headers.Add("Accept-Charset", "UTF-8");
        request.Headers.Add("MaxDataServiceVersion", "3.0;NetFx");
        request.Headers.Add("DataServiceVersion", "1.0;NetFx");
        request.Headers.Add("If-Match", "*");
        request.ContentType = "application/json";


        // Signature string for  Shared Key Lite Authentication must be in the form
        // StringToSign = Date + "\n" + CanonicalizedResource
        // Date 
        string stringToSign = request.Headers["x-ms-date"] + "\n";

        // Canonicalized Resource in the format  /{0}/{1} where 0 is name of the account and 1 is resources URI path
        stringToSign += "/" + storageAccount + "/" + resource;

        // Hash-based Message Authentication Code (HMAC) using SHA256 hash
        var hasher = new HMACSHA256(Convert.FromBase64String(accessKey));

        // Authorization header
        string strAuthorization = "SharedKeyLite " + storageAccount + ":" + Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)));

        // Add the Authorization header to the request
        request.Headers.Add("Authorization", strAuthorization);
        Thread.Sleep(1000);
        // Execute the request
        try
        {
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                using (var r = new StreamReader(response.GetResponseStream()))
                {
                    return (int)response.StatusCode;
                }
            }
        }
        catch (WebException ex)
        {
            // get the message from the exception response
            using (var sr = new StreamReader(ex.Response.GetResponseStream()))
            {
                var res = sr.ReadToEnd();
                // Log res if required
            }

            return (int)ex.Status;
        }
    }

状态 403 意味着您需要进行身份验证才能访问资源。任何体面的服务器都不会为您提供任何包含有关资源的任何信息的信息。因此,无论资源是否存在,您都会得到相同的答复。

根据你的代码,我猜你在使用资源生成授权令牌时,授权令牌有问题。

我建议您可以尝试使用以下代码删除 table 实体。

调用方式:

    AzureTableHelper.DeleteEntity("{storageaccount}", "{accesskey}", "{tablename}", "{partitionkey}", "{rowkey}" );

删除方法:

 public static int DeleteEntity(string storageAccount, string accessKey, string tableName, string partitionkey, string rowkey)
        {

            string host = string.Format(@"https://{0}.table.core.windows.net/", storageAccount);
            string resource = string.Format(@"{0}", tableName) + string.Format("(PartitionKey='{0}',RowKey='{1}')", partitionkey, rowkey);

            string uri = host + resource;

            //if you want to check the etag you need firstly get the etag then delete the entity 
            //string jsonData = "";
            //int responseCode = RequestResource(
            //    storageAccount,
            //    accessKey,
            //    resource,
            //    out jsonData);
            //var jsonObject = JObject.Parse(jsonData);

            //string time = jsonObject.GetValue("odata.etag").ToString();

            //string time = obj.Timestamp;
            // Web request 
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
            request.Method = "DELETE";
            request.ContentType = "application/json";    
            request.Accept = "application/json;odata=nometadata";
            request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
            request.Headers.Add("x-ms-version", "2015-04-05");
            request.Headers.Add("If-Match", "*");
            request.Headers.Add("Accept-Charset", "UTF-8");
            request.Headers.Add("MaxDataServiceVersion", "3.0;NetFx");
            request.Headers.Add("DataServiceVersion", "1.0;NetFx");


            // Signature string for  Shared Key Lite Authentication must be in the form
            // StringToSign = Date + "\n" + CanonicalizedResource
            // Date 
            string stringToSign = request.Headers["x-ms-date"] + "\n";

            // Canonicalized Resource in the format  /{0}/{1} where 0 is name of the account and 1 is resources URI path
            stringToSign += "/" + storageAccount + "/" + resource;

            // Hash-based Message Authentication Code (HMAC) using SHA256 hash
            System.Security.Cryptography.HMACSHA256 hasher = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(accessKey));

            // Authorization header
            string strAuthorization = "SharedKeyLite " + storageAccount + ":" + System.Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)));

            // Add the Authorization header to the request
            request.Headers.Add("Authorization", strAuthorization);

            // Execute the request
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (System.IO.StreamReader r = new System.IO.StreamReader(response.GetResponseStream()))
                    {
                        string jsonResponse = r.ReadToEnd();
                        return (int)response.StatusCode;
                    }
                }
            }
            catch (WebException ex)
            {
                // get the message from the exception response
                using (System.IO.StreamReader sr = new System.IO.StreamReader(ex.Response.GetResponseStream()))
                {
                    string res = sr.ReadToEnd();
                    // Log res if required
                }

                return (int)ex.Status;
            }
        }