Cosmos DB仿真器原始授权值格式

时间:2018-08-22 11:15:58

标签: azure https azure-cosmosdb

我必须从3party应用程序访问cosmos DB存储过程,该应用程序仅允许以原始HTTP格式配置和发送请求。

要模拟我使用了提琴手,但是我不知道在拥有模拟器密钥时如何生成正确的授权令牌。

Cosmos DB默认仿真器密钥为C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==

我的原始请求:

    POST https://localhost:8081/dbs/Orders/colls/volcano1/sprocs/GetDocumentsAndTransform  HTTP/1.1  
x-ms-date: Wed, 09 Dec 2015 18:05:07 GMT  
Cache-Control: no-cache  
authorization: type%3dmaster%26ver%3d1.0%26sig%3dkOU%2bC2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==%3d   
User-Agent: contoso/1.0  
x-ms-version: 2015-08-06  
Accept: application/json  
Content-Type: application/json  
Host: localhost:8081
Content-Length: 9  
Expect: 100-continue  

["World"]  

失败,出现授权问题。有什么想法可以将密钥转换为HTTPs请求的适当授权值吗?

1 个答案:

答案 0 :(得分:2)

您可以看一下Java SDK,它是开源的。 例如。 https://github.com/Azure/azure-cosmosdb-java/blob/master/sdk/src/main/java/com/microsoft/azure/cosmosdb/internal/BaseAuthorizationTokenProvider.java

/**
 * This class is used internally by both client (for generating the auth header with master/system key) and by the Gateway when
* verifying the auth header in the Azure Cosmos DB database service.
 */
public class BaseAuthorizationTokenProvider implements AuthorizationTokenProvider {

private final String masterKey;
private final Mac macInstance;

public BaseAuthorizationTokenProvider(String masterKey) {
    this.masterKey = masterKey;
    byte[] masterKeyDecodedBytes = Utils.Base64Decoder.decode(this.masterKey.getBytes());
    SecretKey signingKey = new SecretKeySpec(masterKeyDecodedBytes, "HMACSHA256");
    try {
        this.macInstance = Mac.getInstance("HMACSHA256");
        this.macInstance.init(signingKey);
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        throw new IllegalStateException(e);
    }
}

/**
 * This API is a helper method to create auth header based on client request using masterkey.
 *
 * @param verb                 the verb
 * @param resourceIdOrFullName the resource id or full name
 * @param  resourceSegment     the resource segment
 * @param headers              the request headers
 * @return the key authorization signature
 */
public String generateKeyAuthorizationSignature(String verb,
        String resourceIdOrFullName,
        String resourceSegment,
        Map<String, String> headers) {
    if (verb == null || verb.isEmpty()) {
        throw new IllegalArgumentException("verb");
    }

    if (resourceIdOrFullName == null) {
        resourceIdOrFullName = "";
    }

    if (resourceSegment == null) {
        throw new IllegalArgumentException("resourceSegment");
    }

    if (headers == null) {
        throw new IllegalArgumentException("headers");
    }

    if (this.masterKey == null || this.masterKey.isEmpty()) {
        throw new IllegalArgumentException("masterKey");
    }

    if(!PathsHelper.isNameBased(resourceIdOrFullName)) {
        resourceIdOrFullName = resourceIdOrFullName.toLowerCase(Locale.ROOT);
    }

    // Skipping lower casing of resourceId since it may now contain "ID" of the resource as part of the FullName
    String body = String.format("%s\n%s\n%s\n",
            verb.toLowerCase(),
            resourceSegment,
            resourceIdOrFullName);

    if (headers.containsKey(HttpConstants.HttpHeaders.X_DATE)) {
        body += headers.get(HttpConstants.HttpHeaders.X_DATE).toLowerCase();
    }

    body += '\n';

    if (headers.containsKey(HttpConstants.HttpHeaders.HTTP_DATE)) {
        body += headers.get(HttpConstants.HttpHeaders.HTTP_DATE).toLowerCase();
    }

    body += '\n';

    Mac mac = null;
    try {
        mac = (Mac) this.macInstance.clone();
    } catch (CloneNotSupportedException e) {
        throw new IllegalStateException(e);
    }

    byte[] digest = mac.doFinal(body.getBytes());

    String auth = Utils.encodeBase64String(digest);

    String authtoken = "type=master&ver=1.0&sig=" + auth;

    return authtoken;
}