美文网首页
AmazonS3 授权 java

AmazonS3 授权 java

作者: 禅兜 | 来源:发表于2020-12-25 16:57 被阅读0次

平时在开发中有这样一种场景,一个账号动态创建桶并生成对象;另外一个只读账号,只有获取对象的权限。这个时候,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

相关文章

网友评论

      本文标题:AmazonS3 授权 java

      本文链接:https://www.haomeiwen.com/subject/gpqinktx.html