Skip to content
This repository was archived by the owner on Jul 19, 2024. It is now read-only.

Commit 9beae8b

Browse files
authored
Merge pull request #517 from Azure/legacy-dev
Legacy dev
2 parents 46a61b1 + d1cce18 commit 9beae8b

File tree

9 files changed

+135
-9
lines changed

9 files changed

+135
-9
lines changed

ChangeLog.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2019.12.06 Version 8.6.0
2+
* Added the skipDecode flag to the generate sas method on CloudBlob. This flag allows the customer to skip the url decode that happens by default on the string to sign right before signing. This resolves some problems with custom values for some of the query parameters when used with third party clients.
3+
14
2019.12.02 Version 8.5.0
25
* Support for HTTP proxy with Basic auth.
36
* Support for HTTP proxy with Digest auth.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ To get the binaries of this library as distributed by Microsoft, ready for use w
3939
<dependency>
4040
<groupId>com.microsoft.azure</groupId>
4141
<artifactId>azure-storage</artifactId>
42-
<version>8.5.0</version>
42+
<version>8.6.0</version>
4343
</dependency>
4444
```
4545

microsoft-azure-storage-samples/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<dependency>
2727
<groupId>com.microsoft.azure</groupId>
2828
<artifactId>azure-storage</artifactId>
29-
<version>8.5.0</version>
29+
<version>8.6.0</version>
3030
</dependency>
3131
<dependency>
3232
<groupId>com.microsoft.azure</groupId>

microsoft-azure-storage-samples/src/com/microsoft/azure/storage/logging/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<dependency>
2727
<groupId>com.microsoft.azure</groupId>
2828
<artifactId>azure-storage</artifactId>
29-
<version>8.5.0</version>
29+
<version>8.6.0</version>
3030
</dependency>
3131
<dependency>
3232
<groupId>com.microsoft.azure</groupId>

microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/SasTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@
3333
import java.io.ByteArrayOutputStream;
3434
import java.io.IOException;
3535
import java.net.HttpURLConnection;
36+
import java.net.MalformedURLException;
3637
import java.net.URI;
3738
import java.net.URISyntaxException;
39+
import java.net.URL;
3840
import java.net.UnknownHostException;
3941
import java.security.InvalidKeyException;
4042
import java.util.*;
@@ -500,6 +502,35 @@ public void eventOccurred(SendingRequestEvent eventArg) {
500502
sasBlob.download(new ByteArrayOutputStream(), null, null, context);
501503
}
502504

505+
@Test
506+
@Category(SlowTests.class)
507+
public void testBlobSaSWithSharedAccessBlobHeadersSkipDecode() throws InvalidKeyException,
508+
IllegalArgumentException, StorageException, URISyntaxException, InterruptedException, IOException {
509+
SharedAccessBlobPolicy sp = createSharedAccessPolicy(EnumSet.of(SharedAccessBlobPermissions.READ,
510+
SharedAccessBlobPermissions.WRITE, SharedAccessBlobPermissions.LIST), 300);
511+
512+
SharedAccessBlobHeaders headers = new SharedAccessBlobHeaders();
513+
headers.setCacheControl("no%20cache");
514+
headers.setContentDisposition("inline; filename=\"My Image.jpg\"; filename*=UTF-8''My%20Image.jpg");
515+
headers.setContentEncoding("gzip%20");
516+
headers.setContentLanguage("da%20");
517+
headers.setContentType("image/png");
518+
519+
String sasToken = this.blob.generateSharedAccessSignature(sp, headers, null, null, null, true);
520+
URL url = new URL(this.blob.getUri() + "?" + sasToken);
521+
522+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
523+
connection.setRequestMethod("GET");
524+
assertEquals(200, connection.getResponseCode());
525+
assertEquals("no%20cache", connection.getHeaderField(Constants.HeaderConstants.CACHE_CONTROL));
526+
assertEquals("inline; filename=\"My Image.jpg\"; filename*=UTF-8''My%20Image.jpg",
527+
connection.getHeaderField(Constants.HeaderConstants.CONTENT_DISPOSITION));
528+
assertEquals("gzip%20", connection.getHeaderField(Constants.HeaderConstants.CONTENT_ENCODING));
529+
assertEquals("da%20", connection.getHeaderField(Constants.HeaderConstants.CONTENT_LANGUAGE));
530+
assertEquals("image/png",
531+
connection.getHeaderField(Constants.HeaderConstants.CONTENT_TYPE));
532+
}
533+
503534
@Test
504535
public void testAppendBlobCopyWithSasAndSnapshot()
505536
throws URISyntaxException, StorageException, InterruptedException, IOException, InvalidKeyException {

microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ public static class HeaderConstants {
765765
/**
766766
* Specifies the value to use for UserAgent header.
767767
*/
768-
public static final String USER_AGENT_VERSION = "8.5.0";
768+
public static final String USER_AGENT_VERSION = "8.6.0";
769769

770770
/**
771771
* The default type for content-type and accept

microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudBlob.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,7 +2207,45 @@ public String generateSharedAccessSignature(final SharedAccessBlobPolicy policy,
22072207
public String generateSharedAccessSignature(
22082208
final SharedAccessBlobPolicy policy, final SharedAccessBlobHeaders headers,
22092209
final String groupPolicyIdentifier, final IPRange ipRange, final SharedAccessProtocols protocols)
2210-
throws InvalidKeyException, StorageException {
2210+
throws StorageException, InvalidKeyException {
2211+
return this.generateSharedAccessSignature(policy, headers, groupPolicyIdentifier, ipRange, protocols, false);
2212+
}
2213+
2214+
/**
2215+
* Returns a shared access signature for the blob using the specified group policy identifier and operation context.
2216+
* Note this does not contain the leading "?".
2217+
*
2218+
* @param policy
2219+
* A <code>{@link SharedAccessPolicy}</code> object that represents the access policy for the shared
2220+
* access signature.
2221+
* @param headers
2222+
* A <code>{@link SharedAccessBlobHeaders}</code> object that represents the optional header values to
2223+
* set for a blob accessed with this shared access signature.
2224+
* @param groupPolicyIdentifier
2225+
* A <code>String</code> that represents the container-level access policy.
2226+
* @param ipRange
2227+
* A {@link IPRange} object containing the range of allowed IP addresses.
2228+
* @param protocols
2229+
* A {@link SharedAccessProtocols} representing the allowed Internet protocols.
2230+
* @param skipDecoding
2231+
* A <code>boolean</code> to indicate that the query parameters should not be decoded before being
2232+
* signed. This should only be used if the customer is sure the values passed are in the desired format.
2233+
* This may be useful in some scenarios where the client is used to generate a sas to a third party that
2234+
* will not be using this sdk to make the requests.
2235+
*
2236+
* @return A <code>String</code> that represents the shared access signature.
2237+
*
2238+
* @throws IllegalArgumentException
2239+
* If the credentials are invalid or the blob is a snapshot.
2240+
* @throws InvalidKeyException
2241+
* If the credentials are invalid.
2242+
* @throws StorageException
2243+
* If a storage service error occurred.
2244+
*/
2245+
public String generateSharedAccessSignature(
2246+
final SharedAccessBlobPolicy policy, final SharedAccessBlobHeaders headers,
2247+
final String groupPolicyIdentifier, final IPRange ipRange, final SharedAccessProtocols protocols,
2248+
boolean skipDecoding) throws InvalidKeyException, StorageException {
22112249

22122250
if (!StorageCredentialsHelper.canCredentialsSignRequest(this.blobServiceClient.getCredentials())) {
22132251
throw new IllegalArgumentException(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
@@ -2218,7 +2256,7 @@ public String generateSharedAccessSignature(
22182256
final String signature = SharedAccessSignatureHelper.generateSharedAccessSignatureHashForBlobAndFile(
22192257
policy, headers, groupPolicyIdentifier, resourceName, ipRange, protocols, this.blobServiceClient,
22202258
this.isSnapshot() ? Constants.QueryConstants.BLOB_SNAPSHOT_SERVICE : Constants.QueryConstants.BLOB_RESOURCE,
2221-
this.getSnapshotID());
2259+
this.getSnapshotID(), skipDecoding);
22222260

22232261
final UriQueryBuilder builder = SharedAccessSignatureHelper.generateSharedAccessSignatureForBlobAndFile(
22242262
policy, headers, groupPolicyIdentifier,

microsoft-azure-storage/src/com/microsoft/azure/storage/core/SharedAccessSignatureHelper.java

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,38 @@ public static String generateSharedAccessSignatureHashForBlobAndFile(final Share
309309
SharedAccessHeaders headers, final String accessPolicyIdentifier, final String resourceName,
310310
final IPRange ipRange, final SharedAccessProtocols protocols, final ServiceClient client,
311311
final String service, final String snapshotId) throws InvalidKeyException, StorageException {
312+
return generateSharedAccessSignatureHashForBlobAndFile(policy, headers, accessPolicyIdentifier, resourceName,
313+
ipRange,protocols, client, service, snapshotId, false);
314+
}
315+
316+
/**
317+
* Get the signature hash embedded inside the Shared Access Signature for the blob or file service.
318+
*
319+
* @param policy
320+
* The shared access policy to hash.
321+
* @param headers
322+
* The optional header values to set for a blob or file accessed with this shared access signature.
323+
* @param accessPolicyIdentifier
324+
* An optional identifier for the policy.
325+
* @param resourceName
326+
* The resource name.
327+
* @param ipRange
328+
* The range of IP addresses to hash.
329+
* @param protocols
330+
* The Internet protocols to hash.
331+
* @param client
332+
* The ServiceClient associated with the object.
333+
* @param skipDecoding
334+
* Skip decoding the string to sign before signing.
335+
*
336+
* @return The signature hash embedded inside the Shared Access Signature.
337+
* @throws InvalidKeyException
338+
* @throws StorageException
339+
*/
340+
public static String generateSharedAccessSignatureHashForBlobAndFile(final SharedAccessPolicy policy,
341+
SharedAccessHeaders headers, final String accessPolicyIdentifier, final String resourceName,
342+
final IPRange ipRange, final SharedAccessProtocols protocols, final ServiceClient client,
343+
final String service, final String snapshotId, boolean skipDecoding) throws InvalidKeyException, StorageException {
312344

313345
String stringToSign = generateSharedAccessSignatureStringToSign(
314346
policy, resourceName, ipRange, protocols, accessPolicyIdentifier);
@@ -341,7 +373,7 @@ public static String generateSharedAccessSignatureHashForBlobAndFile(final Share
341373
contentLanguage == null ? Constants.EMPTY_STRING : contentLanguage,
342374
contentType == null ? Constants.EMPTY_STRING : contentType);
343375

344-
return generateSharedAccessSignatureHashHelper(stringToSign, client.getCredentials());
376+
return generateSharedAccessSignatureHashHelper(stringToSign, client.getCredentials(), skipDecoding);
345377
}
346378

347379
/**
@@ -692,12 +724,34 @@ private static UriQueryBuilder generateSharedAccessSignatureHelper(
692724
*/
693725
private static String generateSharedAccessSignatureHashHelper(String stringToSign, final StorageCredentials creds)
694726
throws StorageException, InvalidKeyException {
727+
return generateSharedAccessSignatureHashHelper(stringToSign, creds, false);
728+
}
729+
730+
/**
731+
* Get the signature hash embedded inside the Shared Access Signature.
732+
*
733+
* @param stringToSign
734+
* The string to decode and hash
735+
* @param creds
736+
* Reference to the {@link StorageCredentials}.
737+
* @param skipDecoding
738+
* Skip decoding the string to sign before signing.
739+
*
740+
* @return The signature hash embedded inside the Shared Access Signature.
741+
*
742+
* @throws InvalidKeyException
743+
* @throws StorageException
744+
*/
745+
private static String generateSharedAccessSignatureHashHelper(String stringToSign, final StorageCredentials creds,
746+
boolean skipDecoding) throws StorageException, InvalidKeyException {
695747

696748
Utility.assertNotNull("credentials", creds);
697749

698750
Logger.trace(null, LogConstants.SIGNING, stringToSign);
699751

700-
stringToSign = Utility.safeDecode(stringToSign);
752+
if (!skipDecoding) {
753+
stringToSign = Utility.safeDecode(stringToSign);
754+
}
701755
return StorageCredentialsHelper.computeHmac256(creds, stringToSign);
702756
}
703757

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<modelVersion>4.0.0</modelVersion>
1111
<groupId>com.microsoft.azure</groupId>
1212
<artifactId>azure-storage</artifactId>
13-
<version>8.5.0</version>
13+
<version>8.6.0</version>
1414
<packaging>jar</packaging>
1515

1616
<name>Microsoft Azure Storage Client SDK</name>

0 commit comments

Comments
 (0)