Azure 存储访问策略,签名不匹配
Azure Stored access policy, Signature did not match
我在尝试使用从策略生成的 Sas 访问 blob(图像)时收到以下错误。 MS 学习项目的一部分:https://docs.microsoft.com/en-us/learn/modules/control-access-to-azure-storage-with-sas/6-exercise-use-stored-access-policies
运行练习了两次,还是一样的结果。知道为什么签名是个问题吗?
AuthenticationFailed
服务器无法验证请求。确保 Authorization header 的值格式正确,包括签名。 RequestId:328fa4c1-401e-004c-49d2-06e232000000 Time:2022-01-11T10:02:52.3736100Z
签名不匹配。使用的签名字符串是 /blob/medicalrecords10150/patient-images patient-images-policy 2020-08-04 c
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Sas;
using Azure.Storage;
namespace patientrecords.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class PatientRecordsController : ControllerBase
{
private readonly ILogger<PatientRecordsController> _logger;
private IConfiguration _iconfiguration;
private BlobContainerClient _container;
private String _storedPolicyID = "patient-images-policy";
public PatientRecordsController(ILogger<PatientRecordsController> logger, IConfiguration iconfiguration)
{
_logger = logger;
_iconfiguration = iconfiguration;
_container = new BlobContainerClient(
_iconfiguration.GetValue<string>("StorageAccount:ConnectionString"),
_iconfiguration.GetValue<string>("StorageAccount:Container")
);
CreateStoredAccessPolicy();
}
// GET PatientRecord
[HttpGet]
public IEnumerable<PatientRecord> Get()
{
List<PatientRecord> records = new List<PatientRecord>();
foreach (BlobItem blobItem in _container.GetBlobs())
{
BlobClient blob = _container.GetBlobClient(blobItem.Name);
var patient = new PatientRecord { name=blob.Name, imageURI=blob.Uri.ToString() };
records.Add(patient);
}
return records;
}
// GET PatientRecord/patient-nnnnnn
[HttpGet("{Name}")]
public PatientRecord Get(string name)
{
BlobClient blob = _container.GetBlobClient(name);
return new PatientRecord { name=blob.Name, imageURI=blob.Uri.AbsoluteUri };
}
// GET PatientRecord/patient-nnnnnn/secure
[HttpGet("{Name}/{secure}")]
public PatientRecord Get(string name, string flag)
{
BlobClient blob = _container.GetBlobClient(name);
return new PatientRecord { name=blob.Name, imageURI=blob.Uri.AbsoluteUri, sasToken=GetBlobSas() };
}
// Build a SAS token for the given blob
private string GetBlobSas(BlobClient blob)
{
// Create a user SAS that only allows reading for a minute
BlobSasBuilder sas = new BlobSasBuilder
{
BlobContainerName = blob.BlobContainerName,
BlobName = blob.Name,
Resource = "b",
ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(1)
};
// Allow read access
sas.SetPermissions(BlobSasPermissions.Read);
// Use the shared key to access the blob
var storageSharedKeyCredential = new StorageSharedKeyCredential(
_iconfiguration.GetValue<string>("StorageAccount:AccountName"),
_iconfiguration.GetValue<string>("StorageAccount:AccountKey")
);
return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
}
// Use a stored access policy for the SAS
private void CreateStoredAccessPolicy()
{
// Create a stored access policy for our blobs
BlobSignedIdentifier identifier = new BlobSignedIdentifier
{
Id = _storedPolicyID,
AccessPolicy = new BlobAccessPolicy
{
//ExpiresOn = DateTimeOffset.UtcNow.AddHours(1),
Permissions = "r"
}
};
_container.SetAccessPolicy(permissions: new BlobSignedIdentifier[] { identifier });
}
// Build a SAS token for the given blob
private string GetBlobSas()
{
// Create a user SAS that only allows reading for a minute
BlobSasBuilder sas = new BlobSasBuilder
{
Identifier = _storedPolicyID
};
// Use the shared key to access the blob
var storageSharedKeyCredential = new StorageSharedKeyCredential(
_iconfiguration.GetValue<string>("StorageAccount:AccountName"),
_iconfiguration.GetValue<string>("StorageAccount:AccountKey")
);
return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
}
}
}
我认为您收到此错误是因为您没有在 GetBlobSas()
方法中指定 blob 容器名称。由于省略了 blob 容器名称,因此会为 $root
blob 容器计算 SAS 令牌。由于 SAS 令牌是为 $root
blob 容器计算的,并且您正在将它与另一个 blob 容器一起使用,因此您会收到此授权失败错误。
我注意到的另一个问题是您没有在 SAS 令牌中包含到期时间。它不在您的访问策略中,也不在您使用访问策略获取 SAS 令牌时。
请尝试使用以下代码:
// Build a SAS token for the given blob
private string GetBlobSas()
{
// Create a user SAS that only allows reading for a minute
BlobSasBuilder sas = new BlobSasBuilder
{
Identifier = _storedPolicyID,
ExpiresOn = DateTimeOffset.UtcNow.AddHours(1),
BlobContainerName = _iconfiguration.GetValue<string>("StorageAccount:Container")
};
// Use the shared key to access the blob
var storageSharedKeyCredential = new StorageSharedKeyCredential(
_iconfiguration.GetValue<string>("StorageAccount:AccountName"),
_iconfiguration.GetValue<string>("StorageAccount:AccountKey")
);
return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
}
您将从上面获得的 SAS 令牌将在创建后 1 小时后过期。
我在尝试使用从策略生成的 Sas 访问 blob(图像)时收到以下错误。 MS 学习项目的一部分:https://docs.microsoft.com/en-us/learn/modules/control-access-to-azure-storage-with-sas/6-exercise-use-stored-access-policies
运行练习了两次,还是一样的结果。知道为什么签名是个问题吗?
AuthenticationFailed
服务器无法验证请求。确保 Authorization header 的值格式正确,包括签名。 RequestId:328fa4c1-401e-004c-49d2-06e232000000 Time:2022-01-11T10:02:52.3736100Z
签名不匹配。使用的签名字符串是 /blob/medicalrecords10150/patient-images patient-images-policy 2020-08-04 c
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Sas;
using Azure.Storage;
namespace patientrecords.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class PatientRecordsController : ControllerBase
{
private readonly ILogger<PatientRecordsController> _logger;
private IConfiguration _iconfiguration;
private BlobContainerClient _container;
private String _storedPolicyID = "patient-images-policy";
public PatientRecordsController(ILogger<PatientRecordsController> logger, IConfiguration iconfiguration)
{
_logger = logger;
_iconfiguration = iconfiguration;
_container = new BlobContainerClient(
_iconfiguration.GetValue<string>("StorageAccount:ConnectionString"),
_iconfiguration.GetValue<string>("StorageAccount:Container")
);
CreateStoredAccessPolicy();
}
// GET PatientRecord
[HttpGet]
public IEnumerable<PatientRecord> Get()
{
List<PatientRecord> records = new List<PatientRecord>();
foreach (BlobItem blobItem in _container.GetBlobs())
{
BlobClient blob = _container.GetBlobClient(blobItem.Name);
var patient = new PatientRecord { name=blob.Name, imageURI=blob.Uri.ToString() };
records.Add(patient);
}
return records;
}
// GET PatientRecord/patient-nnnnnn
[HttpGet("{Name}")]
public PatientRecord Get(string name)
{
BlobClient blob = _container.GetBlobClient(name);
return new PatientRecord { name=blob.Name, imageURI=blob.Uri.AbsoluteUri };
}
// GET PatientRecord/patient-nnnnnn/secure
[HttpGet("{Name}/{secure}")]
public PatientRecord Get(string name, string flag)
{
BlobClient blob = _container.GetBlobClient(name);
return new PatientRecord { name=blob.Name, imageURI=blob.Uri.AbsoluteUri, sasToken=GetBlobSas() };
}
// Build a SAS token for the given blob
private string GetBlobSas(BlobClient blob)
{
// Create a user SAS that only allows reading for a minute
BlobSasBuilder sas = new BlobSasBuilder
{
BlobContainerName = blob.BlobContainerName,
BlobName = blob.Name,
Resource = "b",
ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(1)
};
// Allow read access
sas.SetPermissions(BlobSasPermissions.Read);
// Use the shared key to access the blob
var storageSharedKeyCredential = new StorageSharedKeyCredential(
_iconfiguration.GetValue<string>("StorageAccount:AccountName"),
_iconfiguration.GetValue<string>("StorageAccount:AccountKey")
);
return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
}
// Use a stored access policy for the SAS
private void CreateStoredAccessPolicy()
{
// Create a stored access policy for our blobs
BlobSignedIdentifier identifier = new BlobSignedIdentifier
{
Id = _storedPolicyID,
AccessPolicy = new BlobAccessPolicy
{
//ExpiresOn = DateTimeOffset.UtcNow.AddHours(1),
Permissions = "r"
}
};
_container.SetAccessPolicy(permissions: new BlobSignedIdentifier[] { identifier });
}
// Build a SAS token for the given blob
private string GetBlobSas()
{
// Create a user SAS that only allows reading for a minute
BlobSasBuilder sas = new BlobSasBuilder
{
Identifier = _storedPolicyID
};
// Use the shared key to access the blob
var storageSharedKeyCredential = new StorageSharedKeyCredential(
_iconfiguration.GetValue<string>("StorageAccount:AccountName"),
_iconfiguration.GetValue<string>("StorageAccount:AccountKey")
);
return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
}
}
}
我认为您收到此错误是因为您没有在 GetBlobSas()
方法中指定 blob 容器名称。由于省略了 blob 容器名称,因此会为 $root
blob 容器计算 SAS 令牌。由于 SAS 令牌是为 $root
blob 容器计算的,并且您正在将它与另一个 blob 容器一起使用,因此您会收到此授权失败错误。
我注意到的另一个问题是您没有在 SAS 令牌中包含到期时间。它不在您的访问策略中,也不在您使用访问策略获取 SAS 令牌时。
请尝试使用以下代码:
// Build a SAS token for the given blob
private string GetBlobSas()
{
// Create a user SAS that only allows reading for a minute
BlobSasBuilder sas = new BlobSasBuilder
{
Identifier = _storedPolicyID,
ExpiresOn = DateTimeOffset.UtcNow.AddHours(1),
BlobContainerName = _iconfiguration.GetValue<string>("StorageAccount:Container")
};
// Use the shared key to access the blob
var storageSharedKeyCredential = new StorageSharedKeyCredential(
_iconfiguration.GetValue<string>("StorageAccount:AccountName"),
_iconfiguration.GetValue<string>("StorageAccount:AccountKey")
);
return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
}
您将从上面获得的 SAS 令牌将在创建后 1 小时后过期。