【问题标题】:Error trying to get a value from Azure table storage in JavaScript尝试从 JavaScript 中的 Azure 表存储中获取值时出错
【发布时间】:2015-08-20 22:59:50
【问题描述】:

到目前为止,我一直无法从 JavaScript 查询我的 Azure 表。我按照https://msdn.microsoft.com/en-us/library/azure/dd179428.aspx 的步骤操作,描述了如何验证请求,但到目前为止我只收到了一个 Ajax 错误回调。有谁知道这里出了什么问题?以下是我使用的代码:

CORS 代码(C# 控制台应用程序):

using System;
using System.Collections.Generic;
using System.Windows.Forms;

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.WindowsAzure.Storage.Shared.Protocol;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {

    private const String ACCOUNT_NAME = "<ACCOUNT_NAME>";
    private const String ACCOUNT_KEY = "<ACCOUNT_KEY>";

    public Form1() {
        InitializeComponent();
    }

    private CloudTableClient makeTableClient() {
        String connectionString = "AccountName=" + ACCOUNT_NAME + ";AccountKey=" + ACCOUNT_KEY + ";DefaultEndpointsProtocol=https";
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
        return tableClient;
    }

    private void btnAdd_Click(object sender, EventArgs e) {
        addRule(makeTableClient());
    }

    private void btnRemove_Click(object sender, EventArgs e) {
        removeRule(makeTableClient());
    }

    public void addRule(CloudTableClient tableClient) {
        try {
            CorsRule corsRule = new CorsRule() {
                AllowedHeaders = new List<string> { "*" },
                AllowedMethods = CorsHttpMethods.Connect | CorsHttpMethods.Delete | CorsHttpMethods.Get | CorsHttpMethods.Head | CorsHttpMethods.Merge
                  | CorsHttpMethods.Options | CorsHttpMethods.Post | CorsHttpMethods.Put | CorsHttpMethods.Trace,
                //Since we'll only be calling Query Tables, let's just allow GET verb
                AllowedOrigins = new List<string> { "*" }, //This is the URL of our application.
                ExposedHeaders = new List<string> { "*" },
                MaxAgeInSeconds = 1 * 60 * 60, //Let the browser cache it for an hour
            };
            ServiceProperties serviceProperties = tableClient.GetServiceProperties();
            CorsProperties corsSettings = serviceProperties.Cors;
            corsSettings.CorsRules.Add(corsRule);
            tableClient.SetServiceProperties(serviceProperties);
        } catch (Exception e) {
            txtOutput.Text = e.ToString();
        }
    }

    public void removeRule(CloudTableClient tableClient) {
        try {
            ServiceProperties serviceProperties = tableClient.GetServiceProperties();
            CorsProperties corsSettings = serviceProperties.Cors;
            corsSettings.CorsRules.RemoveAt(0);
            tableClient.SetServiceProperties(serviceProperties);
        } catch (Exception e) {
            txtOutput.Text = e.ToString();
        }
    }
}
}

HTML/JavaScript 代码:

    function CallTableStorage() {
        var accountName = "<ACCOUNT_NAME>";
        var tableName = "<TABLE_NAME>";
        var userId = "<PARTITION_AND_ROW_KEY>";
        var secretKey = "<ACCOUNT_KEY>";

        var partitionKey = userId;
        var rowKey = userId;
        var queryString = encodeURIComponent(tableName + "(PartitionKey='" + partitionKey + "',RowKey='" + rowKey + "')");
        var urlPath = "https://" + accountName + ".table.core.windows.net/" + queryString + "?$select=adid";

        var VERB = "GET";
        var contentMD5 = "";
        var contentType = "text/plain; charset=UTF-8";
        var date = (new Date()).toUTCString();
        var canonicalizedResource = "/" + accountName + "/" + queryString;

        stringToSign = VERB + "\n" + 
               contentMD5 + "\n" + 
               contentType + "\n" +
               date + "\n" +
               canonicalizedResource;

        var signature = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(CryptoJS.enc.Utf8.parse(stringToSign), CryptoJS.enc.Base64.parse(secretKey)));

        $.ajax({
            url: urlPath,
            type: 'GET',
            success: function(data) {
                console.log('Success:', data);
            },
            beforeSend: function (xhr) {
                xhr.setRequestHeader('x-ms-version', '2014-02-14');
                xhr.setRequestHeader('x-ms-date', date);
                xhr.setRequestHeader('Authorization', "SharedKey " + accountName + ":" + signature);
                xhr.setRequestHeader('Accept', 'application/json;odata=nometadata');
                xhr.setRequestHeader('Accept-Charset', 'UTF-8');
                xhr.setRequestHeader('DataServiceVersion', '3.0;NetFx');
                xhr.setRequestHeader('MaxDataServiceVersion', '3.0;NetFx');
                xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
            },
            error: function(data) {
                console.log('Error:', data);
            }
        });
    }
    window.onload = CallTableStorage;

【问题讨论】:

  • 那么错误说明了什么?
  • 哎呀!把它排除在外。我稍微编辑了代码,将成功和错误回调函数输出到控制台以查看详细信息。我还添加了一个缺失的行 xhr.setRequestHeader("Access-Control-Allow-Origin", "*");这显然是需要的(基于我看到的错误)。目前,我看到的错误是:此站点使用 SHA-1 证书;建议您使用具有比 SHA-1 更强的哈希函数的签名算法的证书。
  • 我也从调试器中看到:服务器无法验证请求。确保 Authorization 标头的值正确形成,包括签名。这可能是真正的原因 - 我会继续挖掘。
  • 您能发布一个示例 stringToSign 的值吗?乍一看,您在 stringToSign 中使用的 contentType 似乎从未在请求​​的 Content-Type 标头中设置。
  • 一个示例 stringToSign 看起来像:--- GET text/plain; charset=UTF-8 Mon, 22 Jun 2015 12:37:57 GMT /rbtest/Ads(PartitionKey%3D'johndoe%40microsoft.com'%2CRowKey%3D'johndoe%40microsoft.com') --- 我尝试删除内容-type from stringToSign(如下所示)并添加 xhr.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8');但得到了相同的结果。鉴于文档说 StringToSign 应该如下所示,我本来预计这不会起作用: StringToSign = VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + " \n" + 规范化资源;

标签: javascript ajax azure azure-table-storage


【解决方案1】:

您能否尝试从您的 stringToSign 中删除 content-type 并查看是否可行?或者,正如 Michael Roberson 建议的那样,为 Content-Type 添加一个 setRequestHeader 并查看是否可行。

此外,如果此 javascript/html 用于客户端应用程序,您应该小心,因为您的帐户密钥将以纯文本形式发送。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-04
    • 2017-09-14
    • 2016-05-09
    • 2012-12-18
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    相关资源
    最近更新 更多