平時(shí)在開(kāi)發(fā)中有這樣一種場(chǎng)景夯膀,一個(gè)賬號(hào)動(dòng)態(tài)創(chuàng)建桶并生成對(duì)象继蜡;另外一個(gè)只讀賬號(hào)回俐,只有獲取對(duì)象的權(quán)限。這個(gè)時(shí)候稀并,AmazonS3 需要每創(chuàng)建一個(gè)桶仅颇,就要給只讀賬號(hào)授權(quán)一次。如果桶是經(jīng)常創(chuàng)建的碘举,通過(guò)管理界面控制臺(tái),都這樣授權(quán)忘瓦,不是很方便,也容易忘記做授權(quán)引颈。這個(gè)時(shí)候耕皮,我們可以通過(guò)sdk,在創(chuàng)建桶和上傳對(duì)象的時(shí)候蝙场,給相應(yīng)的只讀賬號(hào)授權(quán)凌停,讓其具有讀對(duì)象的權(quán)限。
讀寫賬號(hào):user-rw
只讀賬號(hào):user-read
1.用讀寫賬號(hào)的創(chuàng)建桶的時(shí)候售滤,授權(quán)只讀賬號(hào)能讀取桶的權(quán)限
// 創(chuàng)建桶
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); //獲取桶的權(quán)限信息
if(acl!=null){
Grantee grantee = new CanonicalGrantee(readUser);
acl.grantPermission(grantee,Permission.Read);//授權(quán)可讀
xskyS3Base.getAmazonS3().setBucketAcl(bucketName,acl);
log.info("桶用戶:{}授權(quán)成功",readUser);
}else{
log.error("通過(guò)桶:{}查詢不到acl信息",bucketName);
}
}
} catch (SdkClientException e) {
log.error("授權(quán)失敗",e);
}
}
- 初始化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;
}
//創(chuàng)建連接
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 的實(shí)例
ClientConfiguration config = new ClientConfiguration();
config.setProtocol(Protocol.HTTP);
config.setUseExpectContinue(false);
config.setMaxConnections(ksKyConifg.getClientMaxConnections()); // 最大連接數(shù) 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");
//創(chuàng)建連接,替換原AmazonS3Client接口
client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withClientConfiguration(config)
.withEndpointConfiguration(end_point)
.withPathStyleAccessEnabled(true)
.build();
return client;
}
}
3.上傳對(duì)象并授予權(quán)限
public PutObjectResult putObject(String bucketName, String key, File file)
{
PutObjectResult putResult = null;
try {
ObjectMetadata metadata = new ObjectMetadata();
PutObjectRequest putRequest = new PutObjectRequest(bucketName, key, file);
//設(shè)置認(rèn)證只讀,這種授權(quán)需要有賬號(hào)的方式才能讀取
putRequest.setCannedAcl(CannedAccessControlList.AuthenticatedRead);
//還有種CannedAccessControlList.PublicRead罚拟,這個(gè)打開(kāi)台诗,會(huì)再瀏覽器地址能直接打開(kāi)下載錄音
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;
}
另外一種方式,也在給每個(gè)對(duì)象設(shè)置權(quán)限赐俗;這種方式需要對(duì)象上傳后拉队,再設(shè)置。這種方式的缺點(diǎn)就是阻逮,單獨(dú)授權(quán)的時(shí)候粱快,需要另外再發(fā)起一次網(wǎng)絡(luò)請(qǐng)求授權(quán)
//對(duì)每個(gè)對(duì)象進(jìn)行授權(quán)
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("授權(quán)對(duì)象的只讀賬號(hào)");
}else{
log.error("根據(jù)桶:{}和key:{}查詢不到對(duì)象的acl信息無(wú)法對(duì)只讀賬號(hào)授權(quán)對(duì)象權(quán)限失敗",bucketName,key);
}
}
} catch (SdkClientException e) {
log.error("只讀賬號(hào)授權(quán)對(duì)象權(quán)限失敗,桶:{}和key:{}",bucketName,key,e);
}
}
其他授權(quán)通知
1.EmailAddressGrantee,可以將對(duì)象發(fā)送到某個(gè)郵件地址
- GroupGrantee 組授權(quán)
直接生成公共的url地址
xskyS3Base.getAmazonS3().setObjectAcl(bucketName, key,CannedAccessControlList.PublicRead);
//獲取一個(gè)request
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucketName, key);
//生成公用的url
URL url = xskyS3Base.getAmazonS3().generatePresignedUrl(urlRequest);
生成過(guò)期時(shí)間的對(duì)象
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); //設(shè)置過(guò)期時(shí)間
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