All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aliyun.sdk.gateway.sls.auth.signer.DefaultSLSSigner Maven / Gradle / Ivy

package com.aliyun.sdk.gateway.sls.auth.signer;

import com.aliyun.auth.credentials.ICredential;
import com.aliyun.auth.signature.SignerParams;
import com.aliyun.auth.signature.signer.SignAlgorithmHmacSHA1;
import com.aliyun.core.http.HttpHeader;
import com.aliyun.core.http.HttpHeaders;
import com.aliyun.core.http.HttpRequest;
import com.aliyun.core.utils.Base64Util;
import com.aliyun.core.utils.StringUtils;
import darabonba.core.TeaRequest;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;

public class DefaultSLSSigner implements SLSSigner {
    private static final String SLS_PREFIX = "x-log-";
    private static final String AUTHORIZATION = "Authorization";
    private static final String CONTENT_MD5 = "Content-MD5";
    private static final String CONTENT_TYPE = "Content-Type";
    private static final String DATE = "Date";
    private static final String NEW_LINE = "\n";
    private static final String AUTHORIZATION_PREFIX = "LOG ";

    @Override
    public HttpRequest sign(TeaRequest request, HttpRequest httpRequest, SignerParams params) {
        final ICredential cred = params.credentials();
        httpRequest.getHeaders().set("x-log-signaturemethod", "hmac-sha1");
        String signature = buildSignature(
                cred.accessKeySecret(),
                request.method().toString(),
                request.pathname(),
                httpRequest.getHeaders(),
                request.query());
        httpRequest.getHeaders().set(AUTHORIZATION, composeRequestAuthorization(cred.accessKeyId(), signature));
        return httpRequest;
    }

    private static String composeRequestAuthorization(String accessKeyId, String signature) {
        return AUTHORIZATION_PREFIX + accessKeyId + ":" + signature;
    }

    private static String buildCanonicalString(String method,
                                               String resourcePath,
                                               HttpHeaders headers, Map query) {

        StringBuilder canonicalString = new StringBuilder();
        canonicalString.append(method).append(NEW_LINE);
        TreeMap headersToSign = new TreeMap<>();

        for (HttpHeader header : headers) {
            if (header == null) {
                continue;
            }
            String lowerKey = header.getName().toLowerCase();
            if (lowerKey.equals(CONTENT_TYPE.toLowerCase())
                    || lowerKey.equals(CONTENT_MD5.toLowerCase())
                    || lowerKey.equals(DATE.toLowerCase())
                    || lowerKey.startsWith(SLS_PREFIX)) {
                headersToSign.put(lowerKey, header.getValue().trim());
            }
        }

        if (!headersToSign.containsKey(CONTENT_TYPE.toLowerCase())) {
            headersToSign.put(CONTENT_TYPE.toLowerCase(), "");
        }
        if (!headersToSign.containsKey(CONTENT_MD5.toLowerCase())) {
            headersToSign.put(CONTENT_MD5.toLowerCase(), "");
        }

        // Append all headers to sign to canonical string
        for (Map.Entry entry : headersToSign.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (key.startsWith(SLS_PREFIX)) {
                canonicalString.append(key).append(':').append(value);
            } else {
                canonicalString.append(value);
            }

            canonicalString.append(NEW_LINE);
        }

        // Append canonical resource to canonical string
        canonicalString.append(buildCanonicalizedResource(resourcePath, query));

        return canonicalString.toString();
    }

    private static String buildCanonicalizedResource(String resourcePath,
                                                     Map parameters) {
        StringBuilder builder = new StringBuilder();
        if (!StringUtils.isEmpty(resourcePath) && resourcePath.contains("?")) {
            int index = resourcePath.lastIndexOf("?");
            builder.append(resourcePath.substring(0, index));
        } else {
            builder.append(resourcePath);
        }
        if (parameters != null) {
            String[] parameterNames = parameters.keySet().toArray(new String[0]);
            Arrays.sort(parameterNames);

            char separator = '?';
            for (String paramName : parameterNames) {
                builder.append(separator);
                builder.append(paramName);
                String paramValue = parameters.get(paramName);
                if (paramValue != null) {
                    builder.append("=").append(paramValue);
                }

                separator = '&';
            }
        }
        return builder.toString();
    }

    private static String computeSignature(String key, String data) {
        try {
            Mac mac = SignAlgorithmHmacSHA1.HmacSHA1.getMac();
            mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8),
                    SignAlgorithmHmacSHA1.HmacSHA1.toString()));
            byte[] signData = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64Util.encodeToString(signData);
        } catch (InvalidKeyException ex) {
            throw new RuntimeException("Invalid key: " + key, ex);
        }
    }

    private static String buildSignature(String secretAccessKey, String httpMethod, String resourcePath,
                                         HttpHeaders headers, Map query) {
        String canonicalString = buildCanonicalString(httpMethod, resourcePath, headers, query);
        return computeSignature(secretAccessKey, canonicalString);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy