【问题标题】:Authorization Failure when accessing Azure table via SAS on Xamarin通过 Xamarin 上的 SAS 访问 Azure 表时授权失败
【发布时间】:2017-01-17 18:25:01
【问题描述】:

我已设置自定义 API 来为我的 Xamarin 应用程序生成 SAS 令牌。在应用程序上收到令牌后,我连接到表并尝试运行 .ExistsAsync() 以确认我可以与表通信。我遇到了正确生成 SAS 的问题(尽管我想知道开始/结束时间是否已关闭),但是当我尝试调用 ExistsAsync() 时出现授权失败。下面列出了我的 SAS 生成 API、调用 ExistsAsync() 的 Xamarin 应用程序方法以及我收到的错误消息。

用于 SAS 生成的自定义 API:

module.exports = {
    "post": function (req, res, next) {
        var azure = require('azure-storage');
        var tableName = req.body.Table;

        // First 2 parameters are account name and key for your service
        var tableService = azure.createTableService('ACCOUNT_NAME', 'ACCOUNT_KEY', 'ACCOUNT_URL');

        // creating the table we want the token for - on the off chance it's not there yet
        tableService.createTableIfNotExists(tableName, function (err, result, response) {
            if (!err) {
                var expiryDate = new Date();
                var startDate = new Date();
                expiryDate.setMinutes(startDate.getMinutes() + 100);
                startDate.setMinutes(startDate.getMinutes() - 100);

                var sharedAccessPolicy = {
                    AccessPolicy: {
                        Permissions: 'raud', // requesting read, add, update and delete
                        Start : startDate,
                        Expiry: expiryDate
                    },
                };

                var tableSAS = tableService.generateSharedAccessSignature(tableName, sharedAccessPolicy);
                res.send(200, { Token : tableSAS });
            } else {
                res.send(500, { Token : "Error creating table"});
            }  
        });
    }
};

表连接的 Xamarin 应用代码(调用 TestDataConnection()):

public async Task<bool> TestDataConnection()
{
    if( tableClient == null ) {
        await ConnectToDatabase();
    }
    CloudTable table = tableClient.GetTableReference("MeasurementJournal");
    bool exists = false;
    try {
        exists = await table.ExistsAsync();
    } catch (Exception e) {
        Debug.WriteLine("Error checking if table exists: " + e.ToString());
    }
    return exists;
}

private async Task<bool> ConnectToDatabase()
{
    // Get credentials
    var credentials = await GetStorageCredentials();

    // Create client
    tableClient = new CloudTableClient(new Uri(Utility.ProjectConstants.tableServiceUrl), credentials);

    return true;
}

/**
 * GetStorageCredentials
 * 
 * Gets storage credentials from sas custom API
 */
private async Task<StorageCredentials> GetStorageCredentials()
{
    string token = "NULL";

    try {
        MobileServiceClient serviceClient = new MobileServiceClient(ACCOUNT_URL);

        //create req
        Model.SasRequest req = new Model.SasRequest();
        req.Table = "MeasurementJournal";

        //send req
        Model.SasResponse response = await serviceClient.InvokeApiAsync<Model.SasRequest, Model.SasResponse>(API_EXTENSION, req, HttpMethod.Post, null);

        //save token from response
        token = response.Token;
    } catch (Exception e) {
        Debug.WriteLine("Received exception: " + e.ToString());
    }
    return new StorageCredentials(token);
}

错误信息:

01-07 16:13:22.374 28311 28311 I mono-stdout: Error checking if table exists: Microsoft.WindowsAzure.Storage.WrappedStorageException (0x80041193): <?xml version="1.0" encoding="utf-16"?>
01-07 16:13:22.374 28311 28311 I mono-stdout: <!--An exception has occurred. For more information please deserialize this message via RequestResult.TranslateFromExceptionMessage.-->
01-07 16:13:22.374 28311 28311 I mono-stdout: <RequestResult>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <HTTPStatusCode>403</HTTPStatusCode>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <HttpStatusMessage>Forbidden</HttpStatusMessage>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <TargetLocation>Primary</TargetLocation>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <ServiceRequestID>f90ae37f-0002-0030-1d33-693dbe000000</ServiceRequestID>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <ContentMd5 />
01-07 16:13:22.374 28311 28311 I mono-stdout:   <Etag />
01-07 16:13:22.374 28311 28311 I mono-stdout:   <RequestDate>Sat, 07 Jan 2017 16:13:22 GMT</RequestDate>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <StartTime>Sat, 07 Jan 2017 22:13:21 GMT</StartTime>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <EndTime>Sat, 07 Jan 2017 22:13:22 GMT</EndTime>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <Error>
01-07 16:13:22.374 28311 28311 I mono-stdout:     <Code>AuthorizationFailure</Code>
01-07 16:13:22.374 28311 28311 I mono-stdout:     <Message>This request is not authorized to perform this operation.
01-07 16:13:22.374 28311 28311 I mono-stdout: RequestId:f90ae37f-0002-0030-1d33-693dbe000000
01-07 16:13:22.374 28311 28311 I mono-stdout: Time:2017-01-07T22:13:22.5850271Z</Message>
01-07 16:13:22.374 28311 28311 I mono-stdout:   </Error>
01-07 16:13:22.374 28311 28311 I mono-stdout:   <ExceptionInfo>
01-07 16:13:22.374 28311 28311 I mono-stdout:     <Type />
01-07 16:13:22.374 28311 28311 I mono-stdout:     <HResult>-2146233088</HResult>
01-07 16:13:22.374 28311 28311 I mono-stdout:     <Message>Unexpected response code, Expected:OK or NotFound, Received:Forbidden</Message>
01-07 16:13:22.374 28311 28311 I mono-stdout:     <Source>Microsoft.WindowsAzure.Storage</Source>
01-07 16:13:22.374 28311 28311 I mono-stdout:     <StackTrace>  at Microsoft.WindowsAzure.Storage.Core.Executor.Executor+&lt;ExecuteAsyncInternal&gt;d__6`1[T].MoveNext () [0x0095a] in &lt;b3bed838f8344d41a1a82c4a3b228bac&gt;:0 </StackTrace>
01-07 16:13:22.374 28311 28311 I mono-stdout:   </ExceptionInfo>
01-07 16:13:22.374 28311 28311 I mono-stdout: </RequestResult> ---> Microsoft.WindowsAzure.Storage.StorageException: Unexpected response code, Expected:OK or NotFound, Received:Forbidden
01-07 16:13:22.374 28311 28311 I mono-stdout:   at Microsoft.WindowsAzure.Storage.Core.Executor.Executor+<ExecuteAsyncInternal>d__6`1[T].MoveNext () [0x0095a] in <b3bed838f8344d41a1a82c4a3b228bac>:0
01-07 16:13:22.374 28311 28311 I mono-stdout: Request Information
01-07 16:13:22.374 28311 28311 I mono-stdout: RequestID:f90ae37f-0002-0030-1d33-693dbe000000
01-07 16:13:22.374 28311 28311 I mono-stdout: RequestDate:Sat, 07 Jan 2017 16:13:22 GMT
01-07 16:13:22.374 28311 28311 I mono-stdout: StatusMessage:Forbidden
01-07 16:13:22.374 28311 28311 I mono-stdout: ErrorCode:AuthorizationFailure

【问题讨论】:

  • CloudTable.ExistsAysnc() 调用查询表 REST API,因此具有 QueryEntity 权限的表 SAS 无权执行此操作。您需要帐户密钥或帐户 SAS 才能运行该方法。
  • 感谢@ZhaoxingLu-Microsoft,我在 azure-storage-net 项目上创建了一个错误并得到了相同的答案。如果您在下面添加您的答案,我会将其标记为正确

标签: azure xamarin xamarin.forms azure-table-storage azure-app-api


【解决方案1】:

CloudTable.ExistsAysnc() 调用 Query Tables REST API,因此具有 QueryEntity 权限的表 SAS 无权执行此操作。您需要帐户密钥或帐户 SAS 才能运行 CloudTable.ExistsAysnc() 方法。

【讨论】:

    【解决方案2】:

    我相信您在库中发现了一个错误。我能够重现此错误。我建议在 Github 上提交相同的问题。

    与此同时,检查表是否存在的另一种方法是查询表并尝试仅获取一条记录。表是空的还是包含任何记录都没有关系。如果表不存在,操作会报404错误。

    这是一个示例代码:

            var cred = new StorageCredentials(accountName, accountKey);
            var account = new CloudStorageAccount(cred, true);
            var client = account.CreateCloudTableClient();
            var table = client.GetTableReference("Hello1");
            var sas = table.GetSharedAccessSignature(new SharedAccessTablePolicy()
            {
                Permissions = SharedAccessTablePermissions.Query,
                SharedAccessExpiryTime = DateTime.UtcNow.AddDays(1),
                SharedAccessStartTime = DateTime.UtcNow.AddDays(-1)
            });
            var tableClient = new CloudTableClient(account.TableEndpoint, new StorageCredentials(sas));
            table = tableClient.GetTableReference("Hello1");
            var queryResult = table.ExecuteQuerySegmented(new TableQuery()
            {
                TakeCount = 1
            }, null);
    

    【讨论】:

    • 我听取了您的建议并在 GitHub 上提交了一个问题。事实证明,表/服务 SAS 不支持 ExistsAsync()
    猜你喜欢
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 2016-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多