2014-02-27 52 views
0

我正在使用CloudStack API,並且遇到了有關提出API請求的問題。我總是得到「{」listtemplatesresponse「:{」errorcode「:401,」errortext「:」無法驗證用戶證書和/或請求籤名「}}」儘管我改變了參數。CloudStack:無法驗證用戶憑據和/或請求籤名

這個錯誤發生在需要的參數一些命令,這是我使用命令:

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

請隨時問我,如果你需要更多的信息。歡迎所有意見和建議!

+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); 
} 
+0

如何排序?我不知道 – user3359384

+0

更新了代碼示例 –

+0

非常感謝您的建議!對於遲到的迴應抱歉,我今天就解決了。 – user3359384

0

你的API密鑰和響應參數必須簽署時,他們似乎是使用的分類URL的一部分。

嘗試改變 回報URLEncoder.encode(Base64.encodeBytes(encryptedBytes), "UTF-8");return URLEncoder.encode(Base64.encodeAsString(encryptedBytes), "UTF-8");

+0

我認爲他是按照這個例子http://support.citrix.com/proddocs/topic/cpbm-21-map/cpbm-generatingsigntre-task.html –