2014-02-27 59 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 –