AmazonS3 授权 java

平时在开发中有这样一种场景,一个账号动态创建桶并生成对象;另外一个只读账号,只有获取对象的权限。这个时候,AmazonS3 需要每创建一个桶,就要给只读账号授权一次。如果桶是经常创建的,通过管理界面控制台,都这样授权,不是很方便,也容易忘记做授权。这个时候,我们可以通过sdk,在创建桶和上传对象的时候,给相应的只读账号授权,让其具有读对象的权限。
读写账号:user-rw
只读账号:user-read

1.用读写账号的创建桶的时候,授权只读账号能读取桶的权限

 // 创建桶
    public Bucket creatingBucket(String bucketName)
    {
        Bucket bucket = null;
        try {
            bucket = xskyS3Base.getAmazonS3().createBucket(bucketName);
        }catch (AmazonServiceException ase) {
            log.error("Caught an AmazonServiceException when create buket:{} Error Message:{},HTTP Status Code:{}," +
                            "AWS Error Code:{},Error Type:{},Request ID:{}",bucketName,
                    ase.getMessage(),ase.getStatusCode(),ase.getErrorCode(),ase.getErrorType(),ase.getRequestId());
            throw new RRException("creatingBucket "+bucketName+" fail");
        }
        grantsBucketAcl(bucketName);
        return bucket;
    }

    public void grantsBucketAcl(String bucketName){
        try {
            String readUser = "user-read"
            if(StringUtils.isNotBlank(readUser)){
                AccessControlList acl = xskyS3Base.getAmazonS3().getBucketAcl(bucketName); //获取桶的权限信息
                if(acl!=null){
                    Grantee grantee = new CanonicalGrantee(readUser);
                    acl.grantPermission(grantee,Permission.Read);//授权可读
                    xskyS3Base.getAmazonS3().setBucketAcl(bucketName,acl);
                   
                    log.info("桶用户:{}授权成功",readUser);
                }else{
                    log.error("通过桶:{}查询不到acl信息",bucketName);
                }
            }
        } catch (SdkClientException e) {
            log.error("授权失败",e);
        }
    }
  1. 初始化amazons3
import com.amazonaws.AmazonClientException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.chain.common.config.KsKyConifg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;


@Component
@Slf4j
public class XskyS3Base {

    @Autowired
    private KsKyConifg ksKyConifg;
    private AmazonS3 client = null;

    @PostConstruct
    private void init(){
        client = intXskyS3Basic(ksKyConifg.getServiceUrl(),ksKyConifg.getKeyId(),ksKyConifg.getKeySecret());
    }


    public AmazonS3 getAmazonS3(){
        return client;
    }
    //创建连接
    private AmazonS3 intXskyS3Basic(String serverUrl, String access_key, String secret_key) {
        AWSCredentials credentials = null;
        try {
            credentials = new BasicAWSCredentials(access_key, secret_key);
        } catch (Exception e) {
            log.error("Authentication failed access_key:{},secret_key:{}",access_key,secret_key,e);
            throw new AmazonClientException(
                    "Authentication failed access_key:"+access_key+",secret_key:"+secret_key, e);
        }
        //初始化S3 configure 的实例
        ClientConfiguration config = new ClientConfiguration();
        config.setProtocol(Protocol.HTTP);
        config.setUseExpectContinue(false);
        config.setMaxConnections(ksKyConifg.getClientMaxConnections());                // 最大连接数 200
        config.setConnectionTimeout(ksKyConifg.getClientConnectionTimeout());//10000
        config.setSocketTimeout(ksKyConifg.getClientSocketTimeout());//30000
        config.setConnectionTTL(ksKyConifg.getClientConnectionTTL());        // CPoolEntry 最大有效值.2 * 60 * 1000
        config.setConnectionMaxIdleMillis(ksKyConifg.getClientConnectionMaxIdleMillis());  // 客户端能接受的最大 Keep-Alive 值 60 * 1000

        config.withUseExpectContinue(false);
        config.withSignerOverride("S3SignerType");
        AwsClientBuilder.EndpointConfiguration end_point = new AwsClientBuilder.EndpointConfiguration(serverUrl, "us-east-1");
        //创建连接,替换原AmazonS3Client接口
        client = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withClientConfiguration(config)
                .withEndpointConfiguration(end_point)
                .withPathStyleAccessEnabled(true)
                .build();
        return client;
    }
}

3.上传对象并授予权限

   public PutObjectResult putObject(String bucketName, String key, File file)
    {
        PutObjectResult putResult = null;
        try {
            ObjectMetadata metadata = new ObjectMetadata();
            PutObjectRequest putRequest = new PutObjectRequest(bucketName, key, file);
                //设置认证只读,这种授权需要有账号的方式才能读取
                putRequest.setCannedAcl(CannedAccessControlList.AuthenticatedRead);
                //还有种CannedAccessControlList.PublicRead,这个打开,会再浏览器地址能直接打开下载录音
            putResult = xskyS3Base.getAmazonS3().putObject(putRequest);
        }catch(AmazonServiceException ase) {
            log.error("Caught an AmazonServiceException when put object of:{} Error Message:{},HTTP Status Code:{}," +
                            "AWS Error Code:{},Error Type:{},Request ID:{} error:{}",key,
                    ase.getMessage(),ase.getStatusCode(),ase.getErrorCode(),ase.getErrorType(),ase.getRequestId(),ase.getErrorMessage(),ase);
            throw new RRException("putObject to bucket:"+bucketName+",key:"+key+" fail");
        }
        return putResult;
    }

另外一种方式,也在给每个对象设置权限;这种方式需要对象上传后,再设置。这种方式的缺点就是,单独授权的时候,需要另外再发起一次网络请求授权

 //对每个对象进行授权
    public void grantsObject(String bucketName,String key){
        try {
            String readUser = "user-read";
            if(StringUtils.isNotBlank(readUser)&&StringUtils.isNotBlank(bucketName)&&StringUtils.isNotBlank(key)){
                AccessControlList acl =  xskyS3Base.getAmazonS3().getObjectAcl(bucketName,key);
                if(acl!=null){
                    Grantee grantee = new CanonicalGrantee(readUser);
                    acl.grantPermission(grantee,Permission.Read);
                    xskyS3Base.getAmazonS3().setObjectAcl(bucketName,key,acl);
                    log.info("授权对象的只读账号");
                }else{
                    log.error("根据桶:{}和key:{}查询不到对象的acl信息无法对只读账号授权对象权限失败",bucketName,key);
                }
            }
        } catch (SdkClientException e) {
            log.error("只读账号授权对象权限失败,桶:{}和key:{}",bucketName,key,e);
        }
    }

其他授权通知
1.EmailAddressGrantee,可以将对象发送到某个邮件地址

  1. GroupGrantee 组授权

直接生成公共的url地址

 xskyS3Base.getAmazonS3().setObjectAcl(bucketName, key,CannedAccessControlList.PublicRead);
            //获取一个request
            GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucketName, key);
            //生成公用的url
            URL url = xskyS3Base.getAmazonS3().generatePresignedUrl(urlRequest);

生成过期时间的对象

  GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucketName, key);
            java.util.Date expiration = new java.util.Date();
            long milliSeconds = expiration.getTime();
            milliSeconds += 1000 * 60 * 60; // Add 1 hour.
            expiration.setTime(milliSeconds);
            urlRequest.setExpiration(expiration); //设置过期时间
            URL url = xskyS3Base.getAmazonS3().generatePresignedUrl(urlRequest);
            
            UploadObject(url);
            
            
         public static void UploadObject(URL url) throws IOException
    {
        HttpURLConnection connection=(HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("PUT");
        OutputStreamWriter out = new OutputStreamWriter(
                connection.getOutputStream());
        out.write("This text uploaded as object.");
        out.close();
        int responseCode = connection.getResponseCode();
        System.out.println("Service returned response code " + responseCode);

    }

参考:
https://zhuanlan.zhihu.com/p/194272308
https://blog.csdn.net/hellozhxy/article/details/84070837
https://blog.csdn.net/anhuidelinger/article/details/9831861

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容