CloudStack:无法验证用户凭据和/或请求签名

时间:2014-02-27 08:27:00

标签: api apache-cloudstack

我现在正在使用CloudStack API,我遇到了发出API请求的问题。我总是得到“{”listtemplatesresponse“:{”errorcode“:401,”errortext“:”无法验证用户凭据和/或请求签名“}}”即使我更改了参数。

在某些需要参数的命令中会出现此错误,这是我使用的命令:

    command=listTemplates&templatefilter=featured 

我不知道我做错了什么,因为它与他人合作。以下是我用来发出API请求的代码:

    try {
        String encodedApiKey = URLEncoder.encode(apiKey.toLowerCase(), "UTF-8");
        ArrayList<String> sortedParams = new ArrayList<String>();
        sortedParams.add("apikey="+encodedApiKey);
        StringTokenizer st = new StringTokenizer(apiUrl, "&");
        while (st.hasMoreTokens()) {
            String paramValue = st.nextToken().toLowerCase();
            String param = paramValue.substring(0, paramValue.indexOf("="));
            String value = URLEncoder.encode(paramValue.substring(paramValue.indexOf("=")+1, paramValue.length()), "UTF-8");
            sortedParams.add(param + "=" + value);
        }

        Collections.sort(sortedParams);
        System.out.println("Sorted Parameters: " + sortedParams);
        String sortedUrl = null;
        boolean first = true;
        for (String param : sortedParams) {
            if (first) {
                sortedUrl = param;
                first = false;
            } else {
                sortedUrl = sortedUrl + "&" + param;
            }
        }

        sortedUrl += "&response=json";          
        System.out.println("sorted URL : " + sortedUrl);
        String encodedSignature = signRequest(sortedUrl, secretKey);
        String finalUrl = host + "?" + apiUrl + "&response=json&apiKey=" + apiKey + "&signature=" + encodedSignature;
        StringBuilder str = new StringBuilder();
        HttpClient client = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(finalUrl);
        HttpResponse response = client.execute(httpGet);
        StatusLine statusLine = response.getStatusLine();
        int statusCode = statusLine.getStatusCode();
        if (statusCode == 200) { // Status OK
            HttpEntity entity = response.getEntity();
            InputStream content = entity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(content));
            String line;
            while ((line = reader.readLine()) != null) {
                str.append(line);
            }
            System.out.println("str: "+str);
            result = str.toString();
            System.out.println("result: "+str);
        }
        else
            System.out.println("Error response!!");
    } catch (Throwable t) {
        System.out.println(t);
    }

这是signRequest函数:

public static String signRequest(String request, String key) {
    try {
        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
        mac.init(keySpec);
        mac.update(request.getBytes());
        byte[] encryptedBytes = mac.doFinal();
        return URLEncoder.encode(Base64.encodeBytes(encryptedBytes), "UTF-8");
    } catch (Exception ex) {
        System.out.println(ex);
    }
    return null;
}

如果您需要更多信息,请随时问我。欢迎所有意见和建议!

2 个答案:

答案 0 :(得分:0)

您是否尝试在之后对进行排序?您已将"&response=json"添加到参数列表中?

E.g。

try {
    String encodedApiKey = URLEncoder.encode(apiKey.toLowerCase(), "UTF-8");
    ArrayList<String> sortedParams = new ArrayList<String>();
    sortedParams.add("apikey="+encodedApiKey);
    sortedParams.add("response=json");
    StringTokenizer st = new StringTokenizer(apiUrl, "&");
    while (st.hasMoreTokens()) {
        String paramValue = st.nextToken().toLowerCase();
        String param = paramValue.substring(0, paramValue.indexOf("="));
        String value = URLEncoder.encode(paramValue.substring(paramValue.indexOf("=")+1, paramValue.length()), "UTF-8");
        sortedParams.add(param + "=" + value);
    }

    Collections.sort(sortedParams);
    System.out.println("Sorted Parameters: " + sortedParams);
    String sortedUrl = null;
    boolean first = true;
    for (String param : sortedParams) {
        if (first) {
            sortedUrl = param;
            first = false;
        } else {
            sortedUrl = sortedUrl + "&" + param;
        }
    }

    System.out.println("sorted URL : " + sortedUrl);
    String encodedSignature = signRequest(sortedUrl, secretKey);
    String finalUrl = host + "?" + apiUrl + "&response=json&apiKey=" + apiKey + "&signature=" + encodedSignature;
    StringBuilder str = new StringBuilder();
    HttpClient client = new DefaultHttpClient();
    HttpGet httpGet = new HttpGet(finalUrl);
    HttpResponse response = client.execute(httpGet);
    StatusLine statusLine = response.getStatusLine();
    int statusCode = statusLine.getStatusCode();
    if (statusCode == 200) { // Status OK
        HttpEntity entity = response.getEntity();
        InputStream content = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(content));
        String line;
        while ((line = reader.readLine()) != null) {
            str.append(line);
        }
        System.out.println("str: "+str);
        result = str.toString();
        System.out.println("result: "+str);
    }
    else
        System.out.println("Error response!!");
} catch (Throwable t) {
    System.out.println(t);
}  

答案 1 :(得分:0)

您的API密钥和响应参数必须是签名时使用的已排序网址的一部分,它们似乎是。

尝试改变 返回URLEncoder.encode(Base64.encodeBytes(encryptedBytes), "UTF-8");return URLEncoder.encode(Base64.encodeAsString(encryptedBytes), "UTF-8");