CONTACT
お問い合わせ

AWS S3へのファイルアップロードと署名付URLによるアクセス制限

AWS S3へのファイルアップロードと署名付URLによるアクセス制限方法を記述する。

目次

AWS S3へのファイルアップロードと署名付URLによるアクセス制限

  1. 概要
  2. 処理シーケンス
  3. ポイント
  4. ソースコード

1.概要

S3にアップロードされた各種ドキュメントファイル(画像、PDF、動画など)に対して有効期限内であればアクセス可能な署名付URLを発行する。
署名付URLは以下のような形式で生成され、署名付URLを発行した都度X-Amz-Signature部分の値が変化するため、
署名付URLは特定システムログイン者のみ知るURLとすることが可能であり、アクセス制御として利用が可能である。

署名付URL

https://<S3バケット名>/<S3オブジェクト名>?
    X-Amz-Algorithm=<リクエストの署名を作成するのに使用したハッシュアルゴリズム>&
    X-Amz-Date=20221121T053410Z&
    X-Amz-SignedHeaders=host&
    X-Amz-Expires=299&
    X-Amz-Credential=<認証情報スコープ:アクセスキー、日付、対象とするリージョン、リクエストするサービス、および終了文字列>&
    X-Amz-Signature=<シグネチャ:都度変化する>

システム構成

2.処理シーケンス

3.ポイント

  • S3にファイル類をアップロードした時点では基本的な権限設定としてはインターネットから不特定多数によるアクセスは不可能となっている。
  • 署名付URL発行した時点から有効期限の間だけは、インターネットからアクセスは不可能となっている。※有効期限が切れるとアクセス時は「AccessDenied」となる
  • 有効期限内の署名付URLは不特定多数からのアクセスは可能となるが、署名がランダムに付与されているためOAuthのアクセスークンと同様の位置づけと考えセキュリティ的には問題無い。
  • S3に保管されたファイルをユーザが参照するため、ファイルサイズの大きなファイルを安価なストレージに配置する事でWebサーバの負荷やWebサーバ付近の回線帯域を圧縮可能。

4.ソースコード

package jp.a_frontier.aws;
    
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.time.Instant;
import java.util.Date;
    
import com.amazonaws.AmazonClientException;
import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;

public class S3_Signature {    
    
    public static void main(String[] args) throws IOException {
    
        AWSCredentials credentials = null;
        try {    
            credentials = new ProfileCredentialsProvider("default").getCredentials();
        } catch (Exception e) {    
            throw new AmazonClientException(    
                    "Cannot load the credentials from the credential profiles file. " +    
                    "Please make sure that your credentials file is at the correct " +    
                    "location (C:\\Users\\XXXXXX\\.aws\\credentials), and is in valid format.",    
                    e);
        }    
    
        AmazonS3 s3 = AmazonS3ClientBuilder.standard()    
            .withCredentials(new AWSStaticCredentialsProvider(credentials))    
            .withRegion("ap-northeast-1")    
            .build();
    
        String bucketName = "MyBucketName";
        String objectKey = "aa.pdf";
    
        System.out.println("===========================================");
        System.out.println("Getting Started with Amazon S3");
        System.out.println("===========================================\n");
    
        System.out.println("Listing buckets");
        for (Bucket bucket : s3.listBuckets()) {    
            System.out.println(" - " + bucket.getName());
        }    
        System.out.println();
            
            
            
        S3Object object = s3.getObject(new GetObjectRequest(bucketName, objectKey));
        System.out.println("Content-Type: "  + object.getObjectMetadata().getContentType());
            
        Date expiration = new Date();
        expiration.setTime(Instant.now().toEpochMilli() + 1000 * 60 * 1);// 有効期限1分    
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey)    
                .withMethod(HttpMethod.GET) // GET のみ許可する    
                .withExpiration(expiration);
            
        URL presignedUrl = s3.generatePresignedUrl(request);
            
        System.out.println("presignedUrl="+presignedUrl);
    }
}