MVC中的Azure blob存储安全选项

时间:2014-07-15 10:39:32

标签: c# asp.net-mvc security azure azure-storage-blobs

我正在开发一种解决方案,其中少数经过身份验证的用户应具有对一组Azure Blob存储容器的完全访问权限。我目前已经实现了一个具有公共访问权限的系统,并且想知道我是否需要进一步使系统复杂化,或者这个系统是否足够安全。我简要介绍了共享访问签名(SAS)的工作原理,但我不确定这是否真的有必要,因此请求您的见解。目标是只允许经过身份验证的用户拥有对blob容器及其内容的完全访问权限。

当前系统以下列方式设置权限(C#,MVC):

// Retrieve a reference to my image container 
myContainer = blobClient.GetContainerReference("myimagescontainer");

// Create the container if it doesn't already exist
if (myContainer.CreateIfNotExists())
{
    // Configure container for public access
    var permissions = myContainer.GetPermissions();
    permissions.PublicAccess = BlobContainerPublicAccessType.Container;
    myContainer.SetPermissions(permissions);
}

因此,只要您拥有完整的URL,所有blob都是完全可访问的,但似乎无法直接通过URL列出容器中的blob:

// This URL allows you to view one single image directly:
'https://mystorageaccount.blob.core.windows.net/mycontainer/mycontainer/image_ea644f08-3263-4a7f-9be7-bc42efbf8939.jpg'

// These URLs appear to return to nothing but an error page:
'https://mystorageaccount.blob.core.windows.net/mycontainer/mycontainer/'
'https://mystorageaccount.blob.core.windows.net/mycontainer/'
'https://mystorageaccount.blob.core.windows.net/'

我发现经过身份验证的用户无法共享完整的网址,允许公开访问单个图片;但是,除了经过身份验证的用户之外,没有人能够直接列出,浏览或访问容器以检索其他图像。

然后我的问题就变成了我是否应该进一步保护系统,例如使用SAS,当它现在看起来按预期工作时,或者让系统保持原样。您可能会理解,如果不是严格需要,我不希望系统复杂化。谢谢!

我最终使用的解决方案如下:)

4 个答案:

答案 0 :(得分:3)

如果您只想要您的身份验证。要获得访问权限的用户必须将容器设为私有。否则它将是公开的,其他人获得“几乎私人”的内容只是时间问题而你作为开发人员会感到尴尬。

方法1:您向授权用户发送链接。 在这种情况下,您将为用户提供SAS链接,并直接从blob下载其内容。 您必须生成具有短访问窗口的SAS签名,以便您的用户可以获取您的内容并下载/打开它,并且在他们离开该站点之后链接将过期并且内容将不再可用。这是因为他们意外地通过网络发送链接,而其他人稍后会访问私人内容。

方法2:您的Web服务器获取内容并将其传递给您的客户 在这种情况下,只有您的Web应用程序才具有访问权限,并且不必生成SAS签名。你返回FileContentResult(在MVC的情况下),你准备好了。缺点是您的Web服务器必须在将文件提供给客户端之前下载文件 - 双重流量。在这里,您必须仔细处理Blob-> Web下载,因为如果3个用户尝试一起下载200 MB文件并将其存储在RAM中 - 它将耗尽。

答案 1 :(得分:3)

我使用Ognyan Dimitrov"方法2"在浏览器窗口中提供存储在私有blob容器中的小PDF("无公共读取访问权限"),如下所示:

public ActionResult ShowPdf()
{
    string fileName = "fileName.pdf";

    var storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
    var blobClient = storageAccount.CreateCloudBlobClient();
    var container = blobClient.GetContainerReference("containerName");
    var blockBlob = container.GetBlockBlobReference(fileName);

    Response.AppendHeader("Content-Disposition", "inline; filename=" + fileName);
    return File(blockBlob.DownloadByteArray(), "application/pdf");
}

配置文件

<configuration>
    <appSettings>
        <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key" />
    </appSettings>
</configuration>

......这对我来说非常合适!

答案 2 :(得分:2)

如果您使用的是公共容器,那么您并不是真正限制对经过身份验证的用户的访问。

如果规范说&#34;只有经过身份验证的用户才能访问&#34;那么我个人会发现使用公共容器是不可接受的。 SAS并不是很难 - 图书馆完成大部分工作。

BTW:list the items in a container的格式为:https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=list

答案 3 :(得分:2)

所以,这就是我最终做的事情。感谢Neil和Ognyan让我到那儿。

它的工作原理如下:

  • 所有图片都是私密的,在没有有效SAS的情况下无法查看
  • blob的添加,删除和修改都是在控制器本身内完成的。这些任务不需要SAS或其他程序。
  • 当要向用户显示图像(匿名或经过身份验证)时,一个函数会生成一个快速到期的SAS,它只允许浏览器在页面生成和刷新时下载图像(或blob),但不能将有用的URL复制/粘贴到外部。

我首先明确将容器权限设置为 Private (根据Ognyan的说法,这也是默认设置):

// Connect to storage account
...

// Retrieve reference to a container. 
myContainer= blobClient.GetContainerReference("mycontainer");

// Create the container if it doesn't already exist.
if (myContainer.CreateIfNotExists())
{
    // Explicitly configure container for private access
    var permissions = myContainer.GetPermissions();
    permissions.PublicAccess = BlobContainerPublicAccessType.Off;
    myContainer.SetPermissions(permissions);   
}

然后,当想要显示图像时,我将一个SAS字符串添加到blob的原始存储路径中:

public string GetBlobPathWithSas(string myBlobName)
{
    // Get container reference
    ...

    // Get the blob, in my case an image
    CloudBlockBlob blob = myContainer.GetBlockBlobReference(myBlobName);        

    // Generate a Shared Access Signature that expires after 1 minute, with Read and List access 
    // (A shorter expiry might be feasible for small files, while larger files might need a 
    // longer access period)
    string sas = myContainer.GetSharedAccessSignature(new SharedAccessBlobPolicy()
    {
        SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(1),
        Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List
    });
    return (blob.Uri.ToString() + sas).ToString();
}

然后我从剃刀视图中调用 GetBlobPathWithSas() -function,这样每次页面刷新都会提供一个有效的路径+ sas 来显示图像:< / p>

<img src="@GetPathWithSas("myImage")" />

一般来说,我觉得这个参考有用:

http://msdn.microsoft.com/en-us/library/ee758387.aspx

希望能帮助别人!