我已经设置了一个自定义API来为我的Xamarin应用生成SAS令牌。一旦我在应用程序上收到令牌,我就连接到表并尝试运行.ExistsAsync()以确认我可以与表通信。我遇到了一个问题,我已经正确生成了SAS(虽然我想知道开始/结束时间是否已关闭),但是当我尝试调用ExistsAsync()时,我收到了授权失败。下面列出的是我的SAS生成API,我的Xamarin应用程序方法调用ExistsAsync(),以及我收到的错误消息。
用于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+<ExecuteAsyncInternal>d__6`1[T].MoveNext () [0x0095a] in <b3bed838f8344d41a1a82c4a3b228bac>: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
答案 0 :(得分:1)
CloudTable.ExistsAysnc()调用Query Tables REST API,因此具有QueryEntity权限的表SAS未获得此操作的授权。您需要帐户密钥或帐户SAS才能运行CloudTable.ExistsAysnc()方法。
答案 1 :(得分:0)
我相信您在图书馆中发现了一个错误。我能够重现这个错误。我建议在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);