이 페이지가 유용했습니까?
이 콘텐츠에 대한 여러분의 의견은 중요합니다. 의견을 알려주십시오.
추가 의견
1500자 남음
Java를 사용하여 Azure Blob 컨테이너에 대한 액세스 제어

Java를 사용하여 Azure Blob 컨테이너에 대한 액세스 제어

업데이트 날짜: 2015년 5월

이 가이드에서는 Azure Blob 저장소 서비스를 사용하여 일반적인 작업을 수행하는 방법을 설명합니다. 샘플은 Java로 작성되었으며 Azure ADK for Java를 사용합니다. 이 가이드에서 다루는 시나리오에는 Blob 컨테이너/Blob/메타데이터 업로드, 나열, 다운로드 및 삭제가 포함됩니다. Java 응용 프로그램에서 생산성을 유지하면서 클라우드 저장소를 안전하게 사용하려면 액세스 제어가 기본적으로 필요하므로, 이 가이드에서는 설명하는 액세스 제어의 유형(공용 액세스, 공유 액세스 서명, 저장된 액세스 정책)에 따라 샘플을 제공합니다. 샘플은 모두 Azure Toolkit for Eclipse(Eclipse용 Azure 도구 키트)를 사용하여 Eclipse에서 Java 응용 프로그램으로 컴파일되었으며 실행됩니다.

이 공용 액세스 관련 섹션의 샘플을 실행하고 나면 Java를 사용하여 다음 작업을 수행할 수 있습니다.

  • Azure 저장소 계정에 대해 저장소 계정 연결 문자열 만들기

  • 저장소 계정에서 새 Blob 컨테이너 만들기

  • 컨테이너 메타데이터, Blob 콘텐츠 및 Blob 메타데이터에 대해 익명 사용자에게 제공되는 공용 액세스 권한 조정

  • 저장소 계정의 Blob 컨테이너에 메타데이터 추가

  • 컴퓨터에서 Azure Blob 컨테이너로 Blob 업로드

  • 저장소 계정의 Blob에 메타데이터 추가

  • 익명 사용자로 컨테이너 메타데이터 읽기

  • 익명 사용자로 컨테이너에 저장된 모든 Blob 나열

  • 익명 사용자로 Blob 메타데이터 읽기

  • Azure 저장소 계정의 Blob을 익명 사용자로 컴퓨터에 다운로드

Java 응용 프로그램에서는 Azure 저장소에 Blob 컨테이너를 만들 수 있습니다. 또한 컨테이너에 저장된 Blob 및 메타데이터에 대한 공용 읽기 권한 수준도 지정할 수 있습니다. 공용 액세스는 컨테이너 또는 Blob의 공용 액세스 URL을 알고 있는 익명 사용자에게 자동으로 제공되는 읽기 권한 수준입니다. 공용 액세스를 사용하여 익명 사용자에게 컨테이너에 대한 쓰기 권한을 제공할 수는 없습니다. Azure 저장소 계정의 계정 키가 없는 사용자에게 쓰기 권한을 제공해야 하는 경우에는 공유 액세스 정책 또는 공유 액세스 서명을 참조하는 URL 형식의 토큰을 해당 사용자에게 제공해야 합니다.

Blob 컨테이너에 대한 공용 액세스가 현재 해제되어 비공개 상태가 아니면 익명 사용자는 다음과 같은 공용 액세스 URL을 사용하여 컨테이너의 모든 Blob을 읽을 수 있습니다.

http://contoso.blob.core.windows.net/container1/image2.jpg

새 Blob 컨테이너의 경우에는 공용 액세스가 기본적으로 해제되지만 공용 액세스를 다시 설정하면 익명 사용자가 공용 액세스 URL을 통해 컨테이너에 대한 읽기 권한을 얻게 됩니다. 공용 액세스를 설정하여 사용자들이 컨테이너의 Blob 하나를 읽을 수 있도록 하지 마세요. 이렇게 하면 전체 컨테이너에 대해 공용 액세스가 설정됩니다. Blob 하나의 공용 액세스 URL을 아는 사용자는 컨테이너에 는 다른 Blob에 대해 작동하는 URL도 추측하여 생성할 수 있습니다. 따라서 공용 액세스 자체는 Blob 컨테이너에 대한 액세스를 제어하기에는 취약한 방법입니다. Blob 콘텐츠 및 컨테이너 메타데이터 액세스를 더욱 강력하게 제어해야 하는 경우에는 공유 액세스 서명 또는 공유 액세스 정책과 컨테이너를 연결해야 합니다.

Azure 저장소 계정에서 새 Blob 컨테이너를 만들거나 계정의 기존 Blob 컨테이너에 대한 공용 액세스 수준을 변경하려면 Azure 저장소 계정의 계정 키와 계정 이름이 필요합니다. 계정 이름과 키를 사용하여 저장소 연결 문자열을 생성해야 합니다. 응용 프로그램은 다음 예제와 비슷한 Java 코드를 사용하여 저장소 연결 문자열을 생성해 반환할 수 있습니다. Azure 저장소 계정 이름 및 계정 키를 제공해야 하는 이 가이드의 모든 예제에서는 같은 Account 클래스를 사용합니다.

public class Account 
{
   private String storageConnectionString;
   public Account()
   {
      this.storageConnectionString =
         "DefaultEndpointsProtocol=http;" + 
         "AccountName=contoso;" + 
         "AccountKey=nPPnnnnPPPPb5nnPnnn5nn5nPnnPnn50P/nnPnPPnPn+PnPPnP/n2nnPPPPn
            Pn55555PPPPn/P5nnP5P+n5n==";
   }
   public String getstorageconnectionstring()
   {
      return storageConnectionString;
   }
} 

이 저장소 계정 문자열을 생성하면 응용 프로그램이 다음과 비슷한 Java 코드를 사용하여 공용 액세스가 OFF로 설정된 새 Blob 컨테이너인 container1을 만들 수 있습니다. container1이 이미 있는 상태에서 이 코드를 실행하면 공용 액세스 수준이 OFF로 다시 설정됩니다. 컨테이너 이름은 소문자여야 합니다.

public class MakeContainer
{
   public static void main(String[] args)
         throws InvalidKeyException, URISyntaxException, StorageException 
   {
      // Exposes the storage account’s secret key
      Account creds = new Account();
      final String storageConnectionString = creds.getstorageconnectionstring();
      CloudStorageAccount storageAccount =
            CloudStorageAccount.parse(storageConnectionString);
      CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
      CloudBlobContainer container =
            blobClient.getContainerReference("container1");
      container.createIfNotExists();
      BlobContainerPermissions containerPermissions =
            new BlobContainerPermissions();
      // All anonymous public access to the container is OFF
      containerPermissions.setPublicAccess(BlobContainerPublicAccessType.OFF);
      container.uploadPermissions(containerPermissions);
      BlobContainerPublicAccessType access1 =
            containerPermissions.getPublicAccess();
      System.out.println("Public access to " + 
            container.getName() + 
            " is set to: " + access1);
   }
}

응용 프로그램은 저장소 계정 문자열을 사용하여 HashMap<문자열, 문자열> 개체 형식으로 컨테이너에 메타데이터를 쓸 수도 있습니다. 예를 들어 다음 Java 코드를 실행하면 container2 메타데이터에 항목 3개가 추가됩니다.

public class AddMetadata
{
   public static void main(String[] args)
         throws InvalidKeyException, URISyntaxException, StorageException
   {
      Account creds = new Account();
      final String storageConnectionString = creds.getstorageconnectionstring();
      CloudStorageAccount storageAccount =
            CloudStorageAccount.parse(storageConnectionString);
      CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
      CloudBlobContainer container = blobClient.getContainerReference("container2");
      container.createIfNotExists();
      HashMap<String, String> meta = new HashMap<String, String>();
      meta.put("city", "San Francisco");
      meta.put("desc", "Photos");
      meta.put("date", "June 2012");
      container.setMetadata(meta);
      container.uploadMetadata();
      System.out.println("Container metadata was added to " + container.getName());
   }
}

여기서는 publicAccess 속성의 값을 BlobContainerPublicAccessType 열거형의 해당 상수인 OFF로 설정하여 container1에 대한 공용 액세스를 해제했습니다. publicAccess 속성의 값은 공용 읽기 권한 수준을 지정하는 다음 3개 상수 중 하나일 수 있습니다.

  • BLOB – 일반 사용자가 이 컨테이너 내의 Blob 메타데이터와 콘텐츠를 읽을 수는 있지만 컨테이너 메타데이터를 읽거나 컨테이너 내의 Blob을 나열할 수는 없습니다.

  • CONTAINER – 일반 사용자가 Blob 콘텐츠 및 메타데이터와 컨테이너 메타데이터를 읽을 수 있으며 컨테이너 내의 Blob을 나열할 수 있습니다.

  • OFF – 공용 액세스를 지정하지 않습니다. 계정 소유자만 이 컨테이너의 리소스를 읽을 수 있습니다.

공용 액세스를 사용하여 익명 사용자에게 쓰기 권한을 제공할 수는 없습니다. 그러나 공용 액세스를 사용하여 Blob 콘텐츠, Blob 메타데이터 및 컨테이너 메타데이터에 대한 읽기 권한을 익명 사용자에게 제공할 수는 있습니다. container2에 대한 공용 액세스를 CONTAINER로 설정한 경우 다음 Java 코드를 실행하면 익명 사용자가 컨테이너 메타데이터를 읽을 수 있습니다. 컨테이너 메타데이터를 읽으려면 컨테이너 개체에 대해 downloadAttributes()를 호출해야 합니다.

public class ReadMetadata
{
   public static void main(String[] args)
         throws InvalidKeyException, URISyntaxException, StorageException
   {
      //Get a reference to the blob container
      //This does not expose the storage account’s secret key
      URI baseuri = new URI("https://contoso.blob.core.windows.net/");
      CloudBlobClient blobclient = new CloudBlobClient(baseuri);
      CloudBlobContainer container = blobclient.getContainerReference("container2");
      container.createIfNotExists();
      //Must be called before reading metadata
      container.downloadAttributes();
      HashMap<String, String> meta = container.getMetadata();
      System.out.println(container.getName() + " contains this metadata." );
      System.out.println(meta.get("city"));
      System.out.println(meta.get("desc"));
      System.out.println(meta.get("date"));
   }
}

공용 액세스에 따라 전체 컨테이너에 대한 공용 읽기 권한이 결정됩니다. 응용 프로그램에서 Blob 하나를 읽을 수 있도록 공용 액세스를 설정하면 일반 사용자가 컨테이너의 모든 Blob을 나열하고 읽을 수 있게 될 수도 있습니다. 예를 들어 다음 Java 코드는 Blob image4.jpg를 container1에 업로드하고 공용 액세스 수준을 OFF에서 CONTAINER로 변경합니다. 마지막으로 Blob image4.jpg와 함께 일부 메타데이터를 추가합니다. image4.jpg 파일은 처음에는 계정 소유자 컴퓨터에 로컬로 저장되어 있던 것입니다.

public class ChangeAccess
{
   public static void main(String[] args)
      throws InvalidKeyException, URISyntaxException,
      StorageException, FileNotFoundException, IOException
   {
      Account creds = new Account();
      final String storageConnectionString =
         creds.getstorageconnectionstring();
      CloudStorageAccount account =
         CloudStorageAccount.parse(storageConnectionString);
      CloudBlobClient serviceClient = account.createCloudBlobClient();
      CloudBlobContainer container =
         serviceClient.getContainerReference("container1");
      container.createIfNotExists();
      BlobContainerPermissions containerPermissions;
      containerPermissions = new BlobContainerPermissions();
      //Anonymous users can list blobs and read blobs and metadata
      containerPermissions.setPublicAccess(BlobContainerPublicAccessType.CONTAINER);
      container.uploadPermissions(containerPermissions);
      CloudBlockBlob blob = container.getBlockBlobReference("image4.jpg");
      //Local source file will be uploaded to blob-container in cloud
      File fileReference = new File ("c:\\myimages\\image4.jpg");
      blob.upload(new FileInputStream(fileReference), fileReference.length());
      BlobContainerPublicAccessType access1 =
         containerPermissions.getPublicAccess();
      System.out.println("Public access to "
         + container.getName() + " is set to: " + access1);
   }
}

공용 액세스 권한 CONTAINER를 사용하는 경우 익명 사용자가 컨테이너의 모든 Blob에 액세스할 수 있을 뿐 아니라, 컨테이너의 모든 Blob을 나열하고 해당 컨테이너에 있는 다른 Blob도 모두 읽을 수 있는 권한을 얻게 됩니다. 다음 코드를 사용하면 익명 사용자가 Blob을 나열할 수 있습니다.

public class EnableAnonymousList
{
   public static void main(String[] args)
      throws InvalidKeyException, URISyntaxException,
      StorageException, FileNotFoundException, IOException
   {
      URI baseuri = new URI("http://wingtiptoys.blob.core.windows.net");
      CloudBlobClient blobclient = new CloudBlobClient(baseuri);
      CloudBlobContainer container = blobclient.getContainerReference("container1");
      for (ListBlobItem blobItem : container.listBlobs())
      {
         System.out.println(blobItem.getUri());
      }
   }
}

container1의 공용 액세스 수준이 CONTAINER이므로 익명 사용자가 다음과 같은 Java 코드를 사용하여 컨테이너의 모든 Blob 콘텐츠와 메타데이터를 읽을 수 있습니다. Blob 메타데이터를 읽으려면 먼저 Blob 개체에 대해 downloadAttributes()를 호출해야 합니다.

public class ReadBlobs
{
   public static void main(String[] args)
      throws InvalidKeyException, URISyntaxException,
      StorageException, FileNotFoundException, IOException
   {
      URI baseuri = new URI("http://wingtiptoys.blob.core.windows.net");
      CloudBlobClient blobclient = new CloudBlobClient(baseuri);
      CloudBlobContainer container = blobclient.getContainerReference("container1");
      String blobName = "image4.jpg";
      CloudBlockBlob blob = container.getBlockBlobReference(blobName);
      // Required to read metadata
      blob.downloadAttributes();
      HashMap<String, String> user = new HashMap<String, String>();
      user = blob.getMetadata();
      String name = (user.get("firstname") + " " + user.get("lastname"));
      String age = ("age: " + user.get("age"));
      String present = ("Presenting talk? " + user.get("presenter"));
      System.out.println(name);
      System.out.println(age);
      System.out.println(present);
      // Image in cloud blob container will be downloaded to local file
      String localFileName = "c:\\myoutputimages\\" + blobName;
      File fileTarget = new File(localFileName);
      blob.download(new FileOutputStream(fileTarget));
      System.out.println("The blob at:\n"  + baseuri +  "/" + container.getName()
         + "/" + blobName + "\nwas downloaded from the cloud to local file:\n"
         + localFileName);
   }  
}

Blob 컨테이너의 공용 액세스 제어는 비교적 사용하기가 쉽지만 Java 응용 프로그램에서 다음 작업을 수행해야 하는 경우에는 공유 액세스 서명 또는 공유 액세스 정책도 구현해야 합니다.

  • 모든 익명 사용자에게 액세스 권한을 노출하지 않고 저장소 계정의 소유자가 아닌 선택한 사용자에게 액세스 권한 제공

  • 저장소 계정의 소유자가 아닌 사용자에 대해 Blob 컨테이너에 대한 임시 쓰기 권한과 읽기 권한 설정

  • 저장소 계정의 소유자가 아닌 사용자의 액세스 권한을 지정된 짧은 시간 동안만 제한적으로 제공

  • 컨테이너에 대한 임시 액세스 권한을 부여한 다음 컨테이너를 삭제하거나 저장소 계정 키를 변경하지 않고 액세스 해지

이 공유 액세스 서명 관련 섹션의 샘플을 실행하고 나면 Java를 사용하여 다음 작업을 수행할 수 있습니다.

  • SAS(공유 액세스 서명) 사용자 한 명 이상에게 임시 컨테이너 액세스 권한을 제공하는 SAS 생성

  • 모든 익명 사용자에게로 액세스 권한을 확장하지 않고 여러 사용자에게 각기 다른 액세스 권한 배포

  • Blob 컨테이너 하나에 대해서만 임시 읽기, 쓰기, 나열 또는 삭제 권한 확장

  • Azure 저장소 계정 키를 모르더라도 개인 컨테이너(공용 액세스 해제) 액세스

  • 기본 SAS를 사용하여 개인 Blob 컨테이너에서 Blob 다운로드

  • 기본 SAS를 사용하여 개인 Blob 컨테이너에 Blob 업로드

  • 개인 컨테이너의 Blob만 나열 또는 삭제

  • 컨테이너 및 Blob 메타데이터 읽기/쓰기

SAS(공유 액세스 서명)에는 Azure Blob 컨테이너에 저장된 Blob에 대해 제어된 액세스 권한을 임의의 사용자에게 제공하는 데 필요한 모든 정보가 포함됩니다. 기본 SAS는 공유 액세스 정책과 연결되지 않으며, 제한된 시간 동안 SAS를 소유한 모든 사용자에게 해지할 수 없는 액세스 권한을 제공합니다. 기본 SAS의 만료 시간은 연장할 수 없습니다. 또한 배포된 SAS는 취소할 수 없으며 만료 시간 전에 컨테이너 액세스 권한을 해지하려면 Azure 저장소 계정 키를 변경해야 합니다.

Azure 저장소 키를 소유한 응용 프로그램은 SharedAccessBlobPolicy 개체의 SharedAccessBlobPermissions 열거형에서 다음 상수 중 하나 이상을 지정하여 저장소 계정에 저장된 Blob 컨테이너에 대한 액세스 제어를 위한 기본 SAS를 생성할 수 있습니다. SAS는 컨테이너 수준에서 액세스를 제어하며, 컨테이너의 모든 Blob에 대해 동일한 액세스 권한을 제공합니다.

  • READ - 컨테이너에 포함된 모든 Blob의 콘텐츠, 속성, 메타데이터 또는 차단 목록을 읽을 수 있습니다. 복사 작업의 원본으로 컨테이너의 Blob을 사용합니다.

  • WRITE - 컨테이너에 포함된 모든 Blob에 대해 콘텐츠, 속성, 메타데이터 또는 차단 목록을 만들거나 쓸 수 있습니다. Blob의 스냅숏을 만들거나 Blob을 임대합니다. Blob의 크기를 조정합니다(페이지 Blob만 해당). 참고: 컨테이너 속성 또는 메타데이터 읽기/쓰기 권한을 부여할 수는 없습니다.

  • DELETE - 컨테이너의 모든 Blob을 삭제합니다. 참고: 전체 컨테이너를 삭제할 수 있는 권한은 부여할 수 없습니다.

  • LIST - 컨테이너의 Blob을 나열합니다.

예를 들어 다음 문자열은 컨테이너에 액세스하는 데 필요한 모든 정보가 포함된 기본 SAS를 나타냅니다.

sp=rwdl&sr=c&sv=2012-02-12&se=2013-03-27T20%3A20%3A21Z&st=2013-03-27T19%3A20%3A21Z&sig=nn5PPPnnPPnPPnnPP%5PPPnnP55P5nnPP5nPn%5P5nnPPn5%5P

SAS URL 생성을 위한 쿼리 매개 변수로 Blob의 공용 액세스 URL에 SAS를 추가할 수 있습니다. SAS는 필요한 모든 정보를 포함하므로 이 URL이 있는 모든 사용자가 액세스 권한을 가지게 됩니다. 작동하는 URL을 생성하려면 공용 액세스 URL과 SAS 사이에 쿼리 기호(?)를 포함해야 합니다.

http://contoso.blob.core.windows.net/container1/image3.jpg?sp=rwdl&sr=c&sv=2012-02-12&se=2013-03-27T20%3A20%3A21Z&st=2013-03-27T19%3A20%3A21Z&sig=nn5PPPnnPPnPPnnPP%5PPPnnP55P5nnPP5nPn%5P5nnPPn5%5P

이 URL은 배포하고 나면 취소하거나 만료 시간을 연장할 수 없습니다. 해당 URL을 얻은 응용 프로그램은 컨테이너의 Blob에 대한 읽기, 쓰기, 나열 및 삭제 권한을 부여받을 수 있습니다. 만료 시간이 지나면 URL은 작동하지 않으며 다시 활성화할 수 없습니다.

다음 Java 코드는 Blob 컨테이너인 container1이 아직 없는 경우에 만듭니다. 그리고 container1의 공용 액세스 수준을 OFF로 설정하며, 적용 가능 기간이 1시간인 기본 SAS 문자열을 생성합니다. 기간은 1시간보다 길게 지정할 수 있습니다. 적용 가능 기간은 즉시 시작되며 1시간 후에 만료됩니다. 적용 가능 기간 동안 SAS를 소유한 모든 사용자는 컨테이너에 대한 READ, WRITE, DELETE, LIST 액세스 권한을 가지게 됩니다. 첫 번째 만료 시간 전에 이 코드를 두 번째로 다시 실행해도 첫 번째 SAS를 통해 적용된 권한이 해지되지는 않으며, 이전 SAS를 기준으로 하는 URL이 계속 작동합니다. 만료 시간이 지나면 만료된 SAS가 추가된 URL은 작동하지 않습니다. 만료 시간 후에 이 코드를 다시 실행하면 추가 1시간 동안 권한을 제공할 수 있는 유효한 SAS가 새로 생성되지만 이전 SAS는 다시 활성화되지 않습니다. 익명 사용자의 컨테이너 액세스는 항상 지정된 공용 액세스 수준을 통해 제어됩니다.

public class BasicSAS
{
   public static void main(String[] args)
      throws InvalidKeyException, URISyntaxException, StorageException
   {
      // Account key required to create SAS
      Account creds = new Account();
      final String storageConnectionString = creds.getstorageconnectionstring();
      CloudStorageAccount storageAccount =
         CloudStorageAccount.parse(storageConnectionString);
      CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
      CloudBlobContainer container = blobClient.getContainerReference("container1");
      container.createIfNotExists();
      SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy();
      GregorianCalendar calendar =
         new GregorianCalendar(TimeZone.getTimeZone("UTC"));
      calendar.setTime(new Date());
      // Immediately applicable
      policy.setSharedAccessStartTime(calendar.getTime());
      // Applicable time span is 1 hour
      calendar.add(Calendar.HOUR, 1);
      policy.setSharedAccessExpiryTime(calendar.getTime());
      // SAS grants all access privileges
      policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ,
         SharedAccessBlobPermissions.WRITE, SharedAccessBlobPermissions.DELETE,
         SharedAccessBlobPermissions.LIST));
      BlobContainerPermissions containerPermissions =
         new BlobContainerPermissions();
      // Private blob-container with no access for anonymous users
      containerPermissions.setPublicAccess(BlobContainerPublicAccessType.OFF);
      container.uploadPermissions(containerPermissions);
      String sas = container.generateSharedAccessSignature(policy,null);
      System.out.println("The basic shared access signature :");
      System.out.println(sas);
   }
}

SAS 적용 가능 기간인 1시간 동안 Blob 컨테이너에 대한 SAS URL을 소유한 응용 프로그램은 다음과 비슷한 Java 코드를 사용하여 container1에 Blob을 쓸 수 있습니다. 공용 액세스를 사용하는 익명 사용자에게는 Blob 컨테이너에 대한 쓰기 권한을 부여할 수 없습니다. 마지막으로, 이미지 작성자에 대한 몇 가지 정보를 Blob과 함께 저장되는 메타데이터로 작성합니다. SAS를 사용한다고 해서 컨테이너 메타데이터에 대한 쓰기 권한을 사용할 수 있는 것은 아닙니다.

다음 Java 코드는 SAS를 소유한 사용자가 Azure 저장소 계정 키를 모르더라도 Blob을 쓸 수 있도록 설정합니다.

public class SASBlober
{
   public static void main(String[] args)
      throws URISyntaxException, FileNotFoundException, StorageException, IOException
   {
      // This does not reveal the secret storage account key
      URI baseuri = new URI("http://wingtiptoys.blob.core.windows.net");
      CloudBlobClient blobclient = new CloudBlobClient(baseuri);
      MyUploadBlob("container1",
         "sp=rwdl&sr=c&sv=2012-02-12&se=2013-03-27T20%3A20%3A21Z&st=2013-03-27T19%3A20%3A21Z&sig=nn5PPPnnPPnPPnnPP%5PPPnnP55P5nnPP5nPn%5P5nnPPn5%5P",
         blobclient);
   }
   
   public static void MyUploadBlob(String containerName, String containerSAS,
      CloudBlobClient blobClient) throws URISyntaxException, StorageException,
      FileNotFoundException, IOException
   {
      //Uploads a local file to blob-container in cloud
      String blobName = "image3.jpg";
      String localFileName = "c:\\myimages\\image3.jpg";
      URI uri = new URI(blobClient.getEndpoint().toString() + "/" +
         containerName + "/" + blobName + "?" + containerSAS);
      CloudBlockBlob sasBlob = new CloudBlockBlob(uri, blobClient);
      HashMap<String, String> user = new HashMap<String, String>();
      user.put("firstname", "Joe");
      user.put("lastname", "Brown" );
      user.put("age", "28");
      user.put("presenter", "no");
      sasBlob.setMetadata(user);
      File fileReference = new File(localFileName);
      sasBlob.upload(new FileInputStream(fileReference), fileReference.length());
      System.out.println("The blob: " + blobName + " has been uploaded to:");
      System.out.println(uri);
   }
}

예제 SAS와 연결된 권한에는 READ가 포함되어 있으므로 SAS URL을 소유한 응용 프로그램은 Azure 저장소 계정 키를 모르더라도 container1의 Blob을 읽은 후에 다음과 비슷한 Java 코드를 사용하여 로컬 파일에 콘텐츠를 쓸 수 있습니다. 마지막으로 이 코드는 Blob과 함께 저장된 메타데이터를 읽고 표시합니다.

public class SASread
{
   public static void main(String[] args)
      throws URISyntaxException, FileNotFoundException, StorageException, IOException
   {
      URI baseuri = new URI("http://wingtiptoys.blob.core.windows.net");
      CloudBlobClient blobclient = new CloudBlobClient(baseuri);
      MyDownloadBlob("container1",
         "sp=rwdl&sr=c&sv=2012-02-12&se=2013-03-27T20%3A20%3A21Z&st=2013-03-27T19%3A20%3A21Z&sig=nn5PPPnnPPnPPnnPP%5PPPnnP55P5nnPP5nPn%5P5nnPPn5%5P",
         blobclient);
   }
   
   public static void MyDownloadBlob(String containerName, String containerSAS, CloudBlobClient blobClient)
      throws URISyntaxException, StorageException, FileNotFoundException, IOException
   {
      //Downloads blob in cloud to local file
      String blobName = "image3.jpg";
      String localFileName = "c:\\myoutputimages\\image3.jpg";
      URI uri = new URI(blobClient.getEndpoint().toString() + "/" +
         containerName + "/" + blobName + "?" + containerSAS);
      CloudBlockBlob sasBlob = new CloudBlockBlob(uri, blobClient);
      File fileTarget = new File(localFileName);
      sasBlob.download(new FileOutputStream(fileTarget));
      HashMap<String, String> user = new HashMap<String, String>();
      user = sasBlob.getMetadata();
      String name = (user.get("firstname") + " " + user.get("lastname"));
      String age = ("age: " + user.get("age"));
      String present = ("Presenting talk? " + user.get("presenter"));
      System.out.println(name);
      System.out.println(age);
      System.out.println(present);
      System.out.println("The blob at:\n"  + uri
         + "\nwas downloaded from the cloud to local file:\n" + localFileName);
   }
}

공용 액세스를 OFF로 설정한 경우 익명 사용자는 container1의 Blob을 나열할 수 없습니다. SAS와 연결된 권한에 LIST가 포함되었으므로 SAS URL을 소유한 사용자는 Azure 저장소 계정 키를 모르더라도 다음 Java 코드를 사용하여 컨테이너의 Blob을 나열할 수 있습니다.

public class ListBlobs 
{
   public static void main(String[] args)
      throws URISyntaxException,StorageException
   {
      URI baseuri = new URI("http://wingtiptoys.blob.core.windows.net");
      CloudBlobClient serviceclient = new CloudBlobClient(baseuri);
      MyList("container1",
         "sp=rwdl&sr=c&sv=2012-02-12&se=2013-03-27T20%3A20%3A21Z&st=2013-03-27T19%3A20%3A21Z&sig=nn5PPPnnPPnPPnnPP%5PPPnnP55P5nnPP5nPn%5P5nnPPn5%5P",
         serviceclient);
   }
   
   public static void MyList(String containerName,
      String containerSAS, CloudBlobClient serviceClient)
      throws URISyntaxException, StorageException
   {
      URI uri = new URI(serviceClient.getEndpoint().toString() + "/"
         + containerName + "?" + containerSAS);
      CloudBlobContainer container = new CloudBlobContainer(uri, serviceClient);
      for (ListBlobItem blobItem : container.listBlobs())
      {
         System.out.println(blobItem.getUri());
      }
   }  
}

SAS와 연결된 권한에 DELETE가 포함되어 있으므로 SAS URL을 소유한 사용자는 container1의 Blob을 삭제할 수 있습니다. 저장소 계정의 Blob 컨테이너를 삭제하는 권한을 사용자에게 부여할 수는 없습니다. SAS를 적용할 수 있는 기간 동안 다음 Java 코드를 실행하면 컨테이너의 기존 Blob이 삭제됩니다.

public class SASDelete
{
   public static void main(String[] args)
      throws URISyntaxException, FileNotFoundException, StorageException, IOException
   {
      URI baseuri = new URI("http://wingtiptoys.blob.core.windows.net");
      CloudBlobClient blobclient = new CloudBlobClient(baseuri);
      MyDeleteBlob("container1",
         "sp=rwdl&sr=c&sv=2012-02-12&se=2013-03-27T20%3A20%3A21Z&st=2013-03-27T19%3A20%3A21Z&sig=nn5PPPnnPPnPPnnPP%5PPPnnP55P5nnPP5nPn%5P5nnPPn5%5P",
         blobclient);
   }
   public static void MyDeleteBlob(String containerName,
      String containerSAS, CloudBlobClient serviceClient)
      throws URISyntaxException, FileNotFoundException, IOException, StorageException
   {
      String blobName = "image4.jpg";
      URI uri = new URI(serviceClient.getEndpoint().toString() + "/" +
         containerName + "/" + blobName + "?" + containerSAS);
      CloudBlockBlob sasBlob = new CloudBlockBlob(uri, serviceClient);
      try
      {
         sasBlob.delete();
         System.out.println(blobName + " was deleted");
      }
      catch (StorageException storageException)
      {
         System.out.println(storageException.getMessage());
         System.exit(-1);
      }
   } 
}

SAS(공유 액세스 서명)를 사용할 때는 이러한 모범 사례에 따라 액세스 권한과 적용 가능 기간 측면 둘 다에서 액세스를 최대한 제한하세요. 공용 액세스는 단순히 컨테이너 및 Blob에 대한 읽기 권한만을 허용하지만, 공유 액세스 서명은 클라우드 기반 리소스에 대한 쓰기 및 삭제 권한을 제공할 수 있습니다. 따라서 원치 않는 사용자에게 SAS URL이 유출되면 저장소 계정에 저장된 리소스가 삭제될 수 있습니다.

  • 공유 액세스 서명은 항상 필요한 최소 권한으로 생성해야 합니다. 즉, READ 권한만 필요한 경우 LIST, WRITE, DELETE 권한도 부여하는 SAS를 배포해서는 안 됩니다.

  • 공유 액세스 서명이 일반 사용자에게는 제공하지 않으려는 권한을 포함하는 경우 HTTPS를 통해 원하는 사용자에게 SAS를 배포합니다. HTTP의 경우 인터넷을 통해 전체 SAS URL이 공개되기 때문입니다.

  • 기본 SAS는 해지할 수 없으므로 항상 컨테이너 수준의 저장 액세스 정책과 연결된 SAS를 생성하는 추가 단계를 수행합니다. 저장된 액세스 정책을 사용하여 만드는 SAS는 Azure 계정 키를 변경하지 않고도 만료 시간 전에 해지할 수 있습니다.

저장된 액세스 정책 관련 섹션의 샘플을 실행하고 나면 Java를 사용하여 다음 작업을 수행할 수 있습니다.

  • 해지, 연장 또는 업데이트 가능한 컨테이너 액세스 권한을 제공하는 정책 SAS 생성

  • Azure 저장소 키를 변경하지 않고 모든 컨테이너 URL을 배포 후 취소

  • 만료 시간 이후 정책 SAS 다시 활성화

  • 언제든지 정책 SAS를 기준으로 URL을 해지/업데이트하고 이전 URL의 동작 변경

  • 단일 컨테이너에 대해 여러 정책 만들기

  • 컨테이너 수준의 액세스 제어를 최대한 유동적으로 활용하기 위해 정책 SAS 및 기본 SAS 함께 사용

응용 프로그램에서 기본 SAS가 아닌 정책 SAS를 사용하는 경우 컨테이너 수준 액세스를 더욱 자세하게 제어할 수 있습니다. 기본 SAS는 적용 가능 기간이 제한되며 배포한 후에는 연장하거나 취소할 수 없습니다. 반면 정책 SAS는 원하는 기간 동안 유효하도록 지정할 수 있으며 언제든지 취소하거나 수정할 수 있습니다. 정책은 SAS URL이 아닌 컨테이너와 함께 저장되므로 SAS 문자열을 변경하거나 URL을 사용자에게 배포하지 않고도 정책을 업데이트할 수 있습니다. 컨테이너의 정책이 업데이트되면 정책 SAS를 사용하여 생성한 모든 이전 URL이 업데이트된 정책을 사용하여 다시 활성화됩니다.

다음 Java 코드는 container1이 아직 없으면 heath라는 정책을 사용하여 Blob container1을 만듭니다. 그리고 container1의 공용 액세스 수준을 OFF로 설정하며, 적용 가능 기간이 3시간인 정책 SAS 문자열을 생성합니다. 적용 가능 기간은 즉시 시작되며 3시간 후에 만료됩니다. 적용 가능 기간 동안 정책 SAS를 소유한 모든 사용자는 컨테이너에 대한 READ, WRITE, DELETE, LIST 액세스 권한을 가지게 됩니다. 만료 시간이 지나면 만료된 SAS를 추가한 URL은 저장소 계정 소유자가 저장소 계정 키를 사용하여 다시 활성화할 때까지 작동하지 않습니다. 익명 사용자의 컨테이너 액세스는 항상 공용 액세스 수준을 통해 제어됩니다.

container1이 있으면 이 코드는 컨테이너에 heath 정책을 추가합니다. Blob 컨테이너는 저장된 액세스 정책을 동시에 4개까지 포함할 수 있습니다. 저장된 여러 액세스 정책을 컨테이너에 할당하는 방법을 보여 주는 코드는 뒷부분에 나와 있습니다. 기본 SAS는 모든 정보를 SAS 문자열에 저장하고 정책 SAS는 해당 정보를 컨테이너와 함께 저장하므로 만료되지 않은 기본 SAS URL의 액세스 권한은 정책 SAS를 추가하거나 수정해도 영향을 받지 않습니다. 컨테이너에 대해 정책 SAS를 만들어 이미 배포된 기본 SAS를 해지할 수는 없습니다.

heath 정책 SAS와 함께 배포한 모든 URL을 해지 및 취소하려면 만료 시간을 시작 시간보다 이전으로 설정하여 코드를 다시 실행합니다. 예를 들어 정책 SAS를 해지하고 사용자에게 배포된 URL에 대한 모든 권한을 취소하려면 다음 코드를 대체합니다.

policy.setSharedAccessStartTime(calendar.getTime());
calendar.add(Calendar.HOUR, -1); //Expiration time is earlier than start time
policy.setSharedAccessExpiryTime(calendar.getTime());

컨테이너에서 정책을 바꾸거나 제거하여 배포 후에 정책 SAS를 해지할 수도 있습니다. 정책 이름을 heath에서 baxter로 변경하여 container1에 대해 코드를 다시 실행하면 새 정책인 baxter가 이전 정책인 heath를 덮어씁니다. 그러면 heath 정책 SAS와 함께 이미 배포된 모든 URL이 취소됩니다. 그러나 heath 정책과 연결된 이전 URL을 다시 활성화할 수 있습니다. 이렇게 하려면 정책을 Baxter에서 heath로 변경하여 코드를 세 번째로 다시 실행합니다. 그러면 Baxter URL이 모두 취소됩니다.

정책 SAS 만료 시간 전이나 후에 다음 Java 코드를 다시 실행하면 추가 3시간 동안 heath 정책 SAS가 갱신되며, 배포된 후 해지되거나 만료된 heath URL이 다시 활성화됩니다. 이 코드를 편집한 후에 다시 실행하여 언제든지 권한을 업데이트(액세스 권한 추가 또는 제거)할 수도 있습니다.

public class PolicySAS
{
   public static void main(String[] args)
      throws InvalidKeyException, URISyntaxException, StorageException
   {
      // Account key required to create SAS
      Account creds = new Account();
      final String storageConnectionString = creds.getstorageconnectionstring();
      CloudStorageAccount storageAccount =
         CloudStorageAccount.parse(storageConnectionString);
      CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
      CloudBlobContainer container = blobClient.getContainerReference("container1");
      container.createIfNotExists();
      SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy();
      GregorianCalendar calendar =
         new GregorianCalendar(TimeZone.getTimeZone("UTC"));
      calendar.setTime(new Date());
      // Immediately applicable
      policy.setSharedAccessStartTime(calendar.getTime());
      // Applicable time-span is 3 hours
      calendar.add(Calendar.HOUR, 3);
      policy.setSharedAccessExpiryTime(calendar.getTime());
      policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ,
            SharedAccessBlobPermissions.WRITE,
            SharedAccessBlobPermissions.DELETE,
            SharedAccessBlobPermissions.LIST));
      BlobContainerPermissions containerPermissions = new BlobContainerPermissions();
      //Private container with no access for anonymous users
      containerPermissions.setPublicAccess(BlobContainerPublicAccessType.OFF);
      //Name the shared access policy: heath
      containerPermissions.getSharedAccessPolicies().put("heath", policy);
      container.uploadPermissions(containerPermissions);
      //Generate the policy SAS string for heath access
      String sas = container.generateSharedAccessSignature(
         new SharedAccessBlobPolicy(),"heath");
      System.out.println("The stored access policy signature:");
      System.out.println(sas);
   } 
}

기본 SAS와 같은 방식으로 Blob의 기본 URL에 정책 SAS를 쿼리 매개 변수로 추가해 제어되는 권한을 포함하는 데코레이팅된 URL을 생성할 수 있습니다. 위의 코드를 통해 생성되는 SAS에는 기본 URL과 정책 SAS 사이에 필요한 쿼리 기호(?)가 포함되어 있지 않습니다. 예를 들어 Blob image3.jpg의 문자열은 다음과 같습니다.

http://contoso.blob.core.windows.net/container1/image3.jpg?sr=c&sv=2012-02-12&sig=nnPn5P5nnPPnn5Pnn5PPnPPPnPPP5PPPPPP%5PPnn5PPn%55&si=heath

응용 프로그램은 정책 SAS를 기본 SAS와 정확히 같은 방식으로 사용할 수 있습니다. 공유 액세스 정책을 사용하여 컨테이너 수준에서 액세스를 제어하려면 이전 예제의 기본 SAS 문자열을 정책 SAS 문자열로 대체하기만 하면 됩니다. 정책 SAS를 소유한 응용 프로그램은 Azure 저장소 계정 키를 모르더라도 컨테이너의 Blob에 대해 읽기, 쓰기, 나열 또는 삭제 작업을 수행할 수 있습니다.

유동적인 컨테이너 수준의 액세스 제어를 구현하는 데 유용한 패턴은 각각 읽기, 쓰기, 나열 및 삭제 권한을 제공하는 저장된 액세스 정책 4개를 컨테이너에 대해 지정하는 것입니다. 이 방식을 사용하더라도 컨테이너에 대해 단기간용 기본 SAS URL을 필요한 대로 배포할 수 있습니다. 기본 SAS URL은 정책과 관계없이 액세스 권한을 제공할 수 있습니다. 다음 Java 코드는 단일 컨테이너에 대해 저장된 액세스 정책 4개를 저장할 수 있는 방법을 보여 줍니다.

public class StoredAccessPolicies
{
   public static void main(String[] args)
      throws InvalidKeyException, URISyntaxException, StorageException
   {
      Account creds = new Account();
      final String storageConnectionString = creds.getstorageconnectionstring();
      CloudStorageAccount storageAccount =
         CloudStorageAccount.parse(storageConnectionString);
      CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
      CloudBlobContainer container = blobClient.getContainerReference("container1");
      container.createIfNotExists();
      BlobContainerPermissions containerPermissions =
         new BlobContainerPermissions();
      containerPermissions.setPublicAccess(BlobContainerPublicAccessType.OFF);
      SharedAccessBlobPolicy read = new SharedAccessBlobPolicy();
      SharedAccessBlobPolicy write = new SharedAccessBlobPolicy();
      SharedAccessBlobPolicy list = new SharedAccessBlobPolicy();
      SharedAccessBlobPolicy delete = new SharedAccessBlobPolicy();
      GregorianCalendar calendar =
         new GregorianCalendar(TimeZone.getTimeZone("UTC"));
      SharedAccessBlobPolicy[] policies =
         new SharedAccessBlobPolicy[]
         {read, write, list, delete};
      calendar.setTime(new Date());
      for(SharedAccessBlobPolicy policy : policies)
      {
         policy.setSharedAccessStartTime(calendar.getTime());
      }
      calendar.add(Calendar.HOUR, 1);
      for(SharedAccessBlobPolicy policy : policies)
      {
         policy.setSharedAccessExpiryTime(calendar.getTime());
      }
      read.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ));
      write.setPermissions(EnumSet.of(SharedAccessBlobPermissions.WRITE));
      list.setPermissions(EnumSet.of(SharedAccessBlobPermissions.LIST));
      delete.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ,
         SharedAccessBlobPermissions.DELETE));
      containerPermissions.getSharedAccessPolicies().put("r", read );
      containerPermissions.getSharedAccessPolicies().put("w", write);
      containerPermissions.getSharedAccessPolicies().put("l", list);
      containerPermissions.getSharedAccessPolicies().put("d", delete);
      container.uploadPermissions(containerPermissions);
      String[] pr = new String[]{"r", "w", "l", "d"};
      for(String p : pr)
      {
         System.out.println(
            container.generateSharedAccessSignature(new SharedAccessBlobPolicy(),p));
      }
   }
}

정책 SAS의 적용 가능 기간 동안 Blob 컨테이너의 기본 URL과 정책 SAS를 소유한 응용 프로그램은 heath가 저장된 액세스 정책과 연결된 권한을 사용할 수 있습니다. 응용 프로그램은 정책 SAS를 기본 SAS와 정확히 같은 방식으로 사용할 수 있습니다. 응용 프로그램이 heath 정책을 사용하여 container1에 대한 컨테이너 수준 액세스를 제어하도록 하려면 이전에 제공된 예제의 기본 SAS 문자열을 정책 SAS 문자열로 대체하기만 하면 됩니다.

참고 항목

표시:
© 2015 Microsoft