2013-04-09 1 views
0

좋습니다. 정말 실망 스럽습니다. 내 API 키를 완벽하게 사용하고 있습니다. 인증은 정상적으로 수행되며 토큰은 정상적으로 생성되며 세션 키도 정상입니다.HTTP POST 요청을 보낼 때 메소드 서명이 유효하지 않습니다.

그러나 playlist.create을 실행하면 재생 목록이 만들어지지 않습니다.

오늘부터 거의 시작부터 시작하여 대부분의 코드를 재 작성했습니다. 성공적으로 16 개의 재생 목록을 만들었습니다. 오류는 없었습니다. 그러나 오늘날에는 같은 코드가 작동하지 않습니다. 나는 그걸 전혀 만지지는 않았지만 오류는 아직 만지지 않았다.

private static void buildPlaylist() { 

    String mood = "Happy"; 
    System.out.println("\nMood is " + mood + "\n\n"); 

    String title = URLEncoder.encode(mood + " " + new Date().getTime(), "UTF-8"); 
    String description = URLEncoder.encode("For when you are " + mood + ". Created by MoodicPlayer.", "UTF-8"); 

    MessageDigest md = MessageDigest.getInstance("MD5"); 

    String apiSig = "api_key" + key + "description" + description + "methodplaylist.createsk" + sessionKey + "title" + title + secret; 
    md.update(apiSig.getBytes()); 
    byte byteData[] = md.digest(); 
    //convert the byte to hex format 
    StringBuffer sb = new StringBuffer(); 
    for (int i = 0; i < byteData.length; i++) { 
     sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)); 
    } 
    String hashedSig = sb.toString(); 

    // FOR DEBUGGING 
    System.out.println("api_key = " + key); 
    System.out.println("api_sig = " + hashedSig); 
    System.out.println("session key = " + sessionKey); 
    // FOR DEBUGGING 

    String urlParameters = "method=playlist.create&api_key="+ key + "&api_sig=" + hashedSig + "&description=" + description + "&sk=" + sessionKey + "&title=" + title; 
    String request = "http://ws.audioscrobbler.com/2.0/"; 

    URL url = new URL(request); 
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
    connection.setDoOutput(true); 
    connection.setDoInput(true); 
    connection.setInstanceFollowRedirects(false); 
    connection.setRequestMethod("POST"); 
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
    connection.setRequestProperty("charset", "utf-8"); 
    connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length)); 
    connection.setUseCaches(false); 

    DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 
    wr.writeBytes(urlParameters); 
    wr.flush(); 
    wr.close(); 

    InputStream is = null; 
    Scanner s = null; 
    try { 
     if (connection.getResponseCode() != 200) { 
      s = new Scanner(connection.getErrorStream()); 
     } else { 
      is = connection.getInputStream(); 
      s = new Scanner(is); 
     } 
     s.useDelimiter("\\Z"); 
     String response = s.next(); 
     System.out.println("\nResponse: " + response + "\n\n"); 
     BufferedWriter out = new BufferedWriter(new FileWriter("requestCreate.xml")); 
     out.write(response); 
     out.close(); 
    } catch (IOException e2) { 
     e2.printStackTrace(); 
    } 

    // FOR DEBUGGING 
    try { 
     System.out.println("Response Code: " + connection.getResponseCode()); 
     System.out.println("Response Message: " + connection.getResponseMessage()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    // FOR DEBUGGING 
    connection.disconnect(); 
} 

그리고 출력 :

내가 코드를 확인했지만, 오류를 찾을 수 없습니다
Starting test for creating playlist... 

Mood is Happy 
api_key = xxxxx 
api_sig = xxxxxx 
session key = xxxxx 

Response: <?xml version="1.0" encoding="utf-8"?> 
<lfm status="failed"> 
<error code="13"> 
    Invalid method signature supplied 
</error> 
</lfm> 


Response Code: 403 
Response Message: Forbidden 

. 나는 코드가 16 시간 전에 괜찮 았음을 의미하고 갑자기 작동하지 않는다!


보안상의 이유로 보안 키를 표시 할 수 없습니다. 그러나 last.fm 세션 키를 찾으려면 빠른 프로그램을 작성했습니다. http://github.com/thekarangoel/LastFMSessionKeyFinder last.fm/api에 등록하기 만하면 API 키와 암호를 프로그램에 입력하면 API 호출을 테스트하는 데 필요한 모든 것이 있습니다.

+0

것 같습니다 :

이 시도해보십시오. 그들은 URL의 일부가되어서는 안됩니까? – Pace

+0

POST 요청이기 때문에 그렇게 생각하지 않습니다. –

답변

2

MD5 해시를 생성 할 때 titledescription 값의 URL 인코딩 버전을 사용하고 있습니다. The documentation은 그렇게 말하지 않습니다. 대신 URL 인코딩되지 않은 값을 사용해보십시오 (UTF-8로 인코딩해야 함). URL 인코딩은 실제 URL 데이터에서만 사용되어야합니다 (이름을 따옴표로 묶으십시오). 당신이 엔터티 본문으로 URL 매개 변수를 작성하는 것처럼

private static void buildPlaylist() { 

    String mood = "Happy"; 
    System.out.println("\nMood is " + mood + "\n\n"); 

    String title = mood + " " + new Date().getTime(); 
    String description = "For when you are " + mood + ". Created by MoodicPlayer."; 

    MessageDigest md = MessageDigest.getInstance("MD5"); 

    String apiSig = "api_key" + key + "description" + description + "methodplaylist.createsk" + sessionKey + "title" + title + secret; 
    md.update(apiSig.getBytes("UTF-8")); 
    byte byteData[] = md.digest(); 
    //convert the byte to hex format 
    StringBuffer sb = new StringBuffer(byteData.length*2); 
    for (int i = 0; i < byteData.length; i++) { 
     sb.append(String.format("%02X", byteData[i]));  
    } 
    String hashedSig = sb.toString(); 

    // FOR DEBUGGING 
    System.out.println("api_key = " + key); 
    System.out.println("api_sig = " + hashedSig); 
    System.out.println("session key = " + sessionKey); 
    // FOR DEBUGGING 

    String urlParameters = "method=playlist.create&api_key="+ key + "&api_sig=" + hashedSig + "&description=" + URLEncoder.encode(description, "UTF-8") + "&sk=" + sessionKey + "&title=" + URLEncoder.encode(title, "UTF-8"); 
    String request = "http://ws.audioscrobbler.com/2.0/"; 

    URL url = new URL(request); 
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
    connection.setDoOutput(true); 
    connection.setDoInput(true); 
    connection.setInstanceFollowRedirects(false); 
    connection.setRequestMethod("POST"); 
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
    connection.setRequestProperty("charset", "utf-8"); 
    connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length)); 
    connection.setUseCaches(false); 

    DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 
    wr.writeBytes(urlParameters); 
    wr.flush(); 
    wr.close(); 

    ... 
} 
+0

시도해 보았지만 작동하지 않습니다. 그리고 API는 실제로 서명을 생성 할 때 매개 변수를 인코딩한다고 말합니다. '매개 변수가 utf8로 인코딩되었는지 확인하십시오.' –

+0

@ user2059238 utf-8 인코딩은 URL 인코딩과 동일하지 않습니다. 이 답변은 정확하고 저에게 효과적입니다 (코드에 누락 된 괄호는 제외). – jkovacs

+0

답변을 복사했지만 403 금지됨 오류가 계속 발생합니다. 왜/어떻게 작동하는지 잘 모르겠습니다. –