0

我现在正在研究 CloudStack API,但我遇到了关于发出 API 请求的问题。即使我更改了参数,我总是得到 "{ "listtemplatesresponse" : {"errorcode":401,"errortext":"unable to verify user credentials and/or request signature"} }"。

此错误发生在一些需要参数的命令中,这是我使用的命令:

    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;
}

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

4

2 回答 2

0

您的 API 密钥和响应参数需要是签名时使用的排序 URL 的一部分,它们似乎是。

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

于 2014-03-10T14:48:03.450 回答
0

添加到参数列表后,您是否尝试过排序?"&response=json"

例如

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);
}  
于 2014-02-28T10:45:50.903 回答