Skip to content

Commit f355845

Browse files
committed
support oss signature version 4.
1 parent 171ee09 commit f355845

18 files changed

+792
-25
lines changed

src/main/java/com/aliyun/oss/OSSClient.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,47 @@ private void initOperations() {
297297
this.downloadOperation = new OSSDownloadOperation(objectOperation);
298298
this.liveChannelOperation = new LiveChannelOperation(this.serviceClient, this.credsProvider);
299299
}
300+
/**
301+
* Sets the product name.
302+
*
303+
* @param product
304+
* the product name, ex oss.
305+
*/
306+
public void setProduct(String product) {
307+
this.bucketOperation.setProduct(product);
308+
this.objectOperation.setProduct(product);
309+
this.multipartOperation.setProduct(product);
310+
this.corsOperation.setProduct(product);
311+
this.liveChannelOperation.setProduct(product);
312+
}
313+
314+
/**
315+
* Sets OSS services Region.
316+
*
317+
* @param region
318+
* OSS services Region.
319+
*/
320+
public void setRegion(String region) {
321+
this.bucketOperation.setRegion(region);
322+
this.objectOperation.setRegion(region);
323+
this.multipartOperation.setRegion(region);
324+
this.corsOperation.setRegion(region);
325+
this.liveChannelOperation.setRegion(region);
326+
}
327+
328+
/**
329+
* Sets OSS cloud box id.
330+
*
331+
* @param cloudBoxId OSS cloud box id.
332+
*/
333+
public void setCloudBoxId(String cloudBoxId) {
334+
this.bucketOperation.setCloudBoxId(cloudBoxId);
335+
this.objectOperation.setCloudBoxId(cloudBoxId);
336+
this.multipartOperation.setCloudBoxId(cloudBoxId);
337+
this.corsOperation.setCloudBoxId(cloudBoxId);
338+
this.liveChannelOperation.setCloudBoxId(cloudBoxId);
339+
}
340+
300341

301342
@Override
302343
public void switchCredentials(Credentials creds) {

src/main/java/com/aliyun/oss/OSSClientBuilder.java

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121

2222
import com.aliyun.oss.common.auth.CredentialsProvider;
2323
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
24+
import com.aliyun.oss.common.comm.SignVersion;
25+
import com.aliyun.oss.common.utils.StringUtils;
26+
import com.aliyun.oss.internal.OSSConstants;
27+
28+
import static com.aliyun.oss.common.utils.CodingUtils.assertParameterNotNull;
2429

2530
/**
2631
* Fluent builder for OSS Client. Use of the builder is preferred over using
@@ -48,7 +53,7 @@ public OSS build(String endpoint, String accessKeyId, String secretAccessKey, Cl
4853

4954
@Override
5055
public OSS build(String endpoint, String accessKeyId, String secretAccessKey, String securityToken,
51-
ClientBuilderConfiguration config) {
56+
ClientBuilderConfiguration config) {
5257
return new OSSClient(endpoint, getDefaultCredentialProvider(accessKeyId, secretAccessKey, securityToken),
5358
getClientConfiguration(config));
5459
}
@@ -79,8 +84,66 @@ private static DefaultCredentialProvider getDefaultCredentialProvider(String acc
7984
}
8085

8186
private static DefaultCredentialProvider getDefaultCredentialProvider(String accessKeyId, String secretAccessKey,
82-
String securityToken) {
87+
String securityToken) {
8388
return new DefaultCredentialProvider(accessKeyId, secretAccessKey, securityToken);
8489
}
8590

91+
public static OSSClientBuilderImpl create() {
92+
return new OSSClientBuilderImpl();
93+
}
94+
95+
public static final class OSSClientBuilderImpl {
96+
private String endpoint;
97+
private CredentialsProvider credentialsProvider;
98+
private ClientConfiguration clientConfiguration;
99+
private String region;
100+
private String cloudBoxId;
101+
102+
private OSSClientBuilderImpl() {
103+
this.clientConfiguration = OSSClientBuilder.getClientConfiguration();
104+
}
105+
106+
public OSSClientBuilderImpl endpoint(String endpoint) {
107+
this.endpoint = endpoint;
108+
return this;
109+
}
110+
111+
public OSSClientBuilderImpl credentialsProvider(CredentialsProvider credentialsProvider) {
112+
this.credentialsProvider = credentialsProvider;
113+
return this;
114+
}
115+
116+
public OSSClientBuilderImpl clientConfiguration(ClientConfiguration clientConfiguration) {
117+
this.clientConfiguration = clientConfiguration;
118+
return this;
119+
}
120+
121+
public OSSClientBuilderImpl region(String region) {
122+
this.region = region;
123+
return this;
124+
}
125+
126+
public OSSClientBuilderImpl cloudBoxId(String cloudBoxId) {
127+
this.cloudBoxId = cloudBoxId;
128+
return this;
129+
}
130+
131+
public OSS build() {
132+
assertParameterNotNull(endpoint, "endpoint");
133+
assertParameterNotNull(credentialsProvider, "credentialsProvider");
134+
assertParameterNotNull(clientConfiguration, "clientConfiguration");
135+
if (SignVersion.V4.equals(clientConfiguration.getSignatureVersion())) {
136+
assertParameterNotNull(region, "region");
137+
}
138+
OSSClient client = new OSSClient(endpoint, credentialsProvider, clientConfiguration);
139+
if (!StringUtils.isNullOrEmpty(region)) {
140+
client.setRegion(region);
141+
}
142+
if (!StringUtils.isNullOrEmpty(cloudBoxId)) {
143+
client.setProduct(OSSConstants.PRODUCT_CLOUD_BOX);
144+
client.setCloudBoxId(cloudBoxId);
145+
}
146+
return client;
147+
}
148+
}
86149
}

src/main/java/com/aliyun/oss/common/auth/HmacSHA1Signature.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,7 @@ public String computeSignature(String key, String data) {
6161
}
6262
}
6363

64+
public byte[] computeHash(byte[] key, byte[] data) {
65+
return sign(key, data, macInstance, LOCK, ALGORITHM);
66+
}
6467
}

src/main/java/com/aliyun/oss/common/auth/HmacSHA256Signature.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,8 @@ public String computeSignature(String key, String data) {
6060
throw new RuntimeException("Unsupported algorithm: " + DEFAULT_ENCODING, ex);
6161
}
6262
}
63+
64+
public byte[] computeHash(byte[] key, byte[] data) {
65+
return sign(key, data, macInstance, LOCK, ALGORITHM);
66+
}
6367
}

src/main/java/com/aliyun/oss/common/auth/ServiceSignature.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ public abstract class ServiceSignature {
5454
*/
5555
public abstract String computeSignature(String key, String data);
5656

57+
/**
58+
* Computes the hash of the data by the given key.
59+
*
60+
* @param key
61+
* The key for the signature.
62+
* @param data
63+
* The data to compute the hash on.
64+
* @return The hash in byte array.
65+
*/
66+
public abstract byte[] computeHash(byte[] key, byte[] data);
67+
5768
/**
5869
*
5970
* Creates the default <code>ServiceSignature</code> instance which is
@@ -65,6 +76,21 @@ public static ServiceSignature create() {
6576
return new HmacSHA1Signature();
6677
}
6778

79+
/**
80+
*
81+
* Creates the <code>ServiceSignature</code> instance by the algorithm
82+
*
83+
* @return The <code>ServiceSignature</code> instance
84+
*/
85+
public static ServiceSignature create(String algorithm) {
86+
if ("HmacSHA256".equals(algorithm)) {
87+
return new HmacSHA256Signature();
88+
} else if ("HmacSHA1".equals(algorithm)) {
89+
return new HmacSHA1Signature();
90+
}
91+
throw new RuntimeException("Unsupported algorithm: " + algorithm);
92+
}
93+
6894
protected byte[] sign(byte[] key, byte[] data, Mac macInstance, Object lock, String algorithm) {
6995
try {
7096
// Because Mac.getInstance(String) calls a synchronized method, it

src/main/java/com/aliyun/oss/common/comm/SignVersion.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22

33
public enum SignVersion {
44
V1,
5-
V2
5+
V2,
6+
V4
67
}

src/main/java/com/aliyun/oss/common/utils/BinaryUtil.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.security.NoSuchAlgorithmException;
2424

2525
import org.apache.commons.codec.binary.Base64;
26+
import org.apache.commons.codec.binary.Hex;
2627

2728
public class BinaryUtil {
2829

@@ -58,4 +59,27 @@ public static String encodeMD5(byte[] binaryData) {
5859
}
5960
return new String(buf);
6061
}
62+
63+
public static byte[] calculateSha256(byte[] binaryData) {
64+
MessageDigest messageDigest = null;
65+
try {
66+
messageDigest = MessageDigest.getInstance("SHA-256");
67+
} catch (NoSuchAlgorithmException e) {
68+
throw new RuntimeException("SHA-256 algorithm not found.");
69+
}
70+
messageDigest.update(binaryData);
71+
return messageDigest.digest();
72+
}
73+
74+
/**
75+
* Converts byte data to a Hex-encoded string in lower case.
76+
*
77+
* @param data
78+
* data to hex encode.
79+
*
80+
* @return hex-encoded string.
81+
*/
82+
public static String toHex(byte[] data) {
83+
return Hex.encodeHexString(data);
84+
}
6185
}

src/main/java/com/aliyun/oss/common/utils/HttpUtil.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package com.aliyun.oss.common.utils;
2121

22+
import static com.aliyun.oss.internal.OSSConstants.DEFAULT_CHARSET_NAME;
2223
import static com.aliyun.oss.internal.OSSUtils.OSS_RESOURCE_MANAGER;
2324
import static com.aliyun.oss.common.utils.CodingUtils.isNullOrEmpty;
2425

@@ -30,6 +31,12 @@
3031

3132
public class HttpUtil {
3233

34+
private static final String[] ENCODED_CHARACTERS_WITH_SLASHES = new String[]{"+", "*", "%7E", "%2F"};
35+
private static final String[] ENCODED_CHARACTERS_WITH_SLASHES_REPLACEMENTS = new String[]{"%20", "%2A", "~", "/"};
36+
37+
private static final String[] ENCODED_CHARACTERS_WITHOUT_SLASHES = new String[]{"+", "*", "%7E"};
38+
private static final String[] ENCODED_CHARACTERS_WITHOUT_SLASHES_REPLACEMENTS = new String[]{"%20", "%2A", "~"};
39+
3340
/**
3441
* Encode a URL segment with special chars replaced.
3542
*/
@@ -58,6 +65,21 @@ public static String urlDecode(String value, String encoding) {
5865
}
5966
}
6067

68+
public static String urlEncode(String value, boolean ignoreSlashes) {
69+
if (value == null) {
70+
return "";
71+
}
72+
try {
73+
String encoded = URLEncoder.encode(value, DEFAULT_CHARSET_NAME);
74+
if (!ignoreSlashes) {
75+
return StringUtils.replaceEach(encoded, ENCODED_CHARACTERS_WITHOUT_SLASHES, ENCODED_CHARACTERS_WITHOUT_SLASHES_REPLACEMENTS);
76+
}
77+
return StringUtils.replaceEach(encoded, ENCODED_CHARACTERS_WITH_SLASHES, ENCODED_CHARACTERS_WITH_SLASHES_REPLACEMENTS);
78+
} catch (UnsupportedEncodingException e) {
79+
throw new IllegalArgumentException(OSS_RESOURCE_MANAGER.getString("FailedToEncodeUri"), e);
80+
}
81+
}
82+
6183
/**
6284
* Encode request parameters to URL segment.
6385
*/

0 commit comments

Comments
 (0)