13

現在、OAuth-Signpost Java ライブラリを使用して、クライアントから OAuth 認証を実装するサーバーに送信されるリクエストに署名しています。(HttpURLConnection を使用して) GET 要求を行うと、すべて正常に機能します。要求は署名され、パラメーターが含まれ、署名は宛先で一致します。ただし、POST リクエストでは機能しないようです。HttpURLConnection を使用して POST に署名するときに発生する可能性のある問題を認識しているため、これらの要求のために Apache HttpComponents ライブラリに移動しました。次の例で送信するパラメーターは、プレーンな文字列と XML に似た文字列 ('rxml') です。私のコードは次のようになります。

public Response exampleMethod(String user, String sp, String ep, String rn, String rxml){

   //All these variables are proved to be correct (they work right in GET requests)
    String uri = "...";
    String consumerKey = "...";
    String consumerSecret = "...";
    String token = "...";
    String secret = "...";

  //create the parameters list
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("user", user));
    params.add(new BasicNameValuePair("sp", sp));
    params.add(new BasicNameValuePair("ep", ep));
    params.add(new BasicNameValuePair("rn", rn));
    params.add(new BasicNameValuePair("rxml", rxml));

   // create a consumer object and configure it with the access
   // token and token secret obtained from the service provider
    OAuthConsumer consumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
    consumer.setTokenWithSecret(token, secret);

   // create an HTTP request to a protected resource
    HttpPost request = new HttpPost(uri);

   // sign the request      
    consumer.sign(request);       

   // set the parameters into the request
    request.setEntity(new UrlEncodedFormEntity(params));

   // send the request
    HttpClient httpClient = new DefaultHttpClient();
    HttpResponse response = httpClient.execute(request);

   //if request was unsuccessful
    if(response.getStatusLine().getStatusCode()!=200){
        return Response.status(response.getStatusLine().getStatusCode()).build();
    }

   //if successful, return the response body
    HttpEntity resEntity = response.getEntity();
    String responseBody = "";

    if (resEntity != null) {
        responseBody = EntityUtils.toString(resEntity);
    }

    EntityUtils.consume(resEntity);

    httpClient.getConnectionManager().shutdown();

    return Response.status(200).entity(responseBody).build();

}

サーバーに POST リクエストを送信すると、署名 (送信した署名とサーバーが独自に計算した署名) が一致しないというエラーが表示されるので、署名しているベース文字列に関係していると思います。両側で同じキーとシークレットを処理しているため (チェック済み)、POST 署名のしくみ。

これを行う方法は、パラメーターを URL の一部として設定することです (GET 要求のように)。ただし、XML パラメータが URL の長さを超える可能性があるため、POST パラメータとして送信する必要があるため、私にはうまくいきません。

POST リクエストに署名するか、パラメーターを処理するかのいずれかで何か間違っていると思いますが、それが何であるかはわかりません。助けてください。

PS: この問題に関するコンテキスト、エラー トレース、または追加情報が不足している場合は申し訳ありませんが、私は初心者です。そのため、必要な場合はお気軽にお問い合わせください。

4

3 に答える 3

6

少し裏話/説明

私は過去数日間同様の問題を抱えていて、ほとんどあきらめていました. 私が通信していたサービスを立ち上げていた私の会社の人が、ヘッダーパラメーターではなくクエリ文字列から OAuth 情報を読み取るように構成していたと聞くまでは.

したがって、Signpost が署名するためにリクエストに渡すヘッダー パラメータ Authorization から読み取るのではなく、たとえば[Authorization: OAuth oauth_consumer_key="USER", oauth_nonce="4027096421883800497", oauth_signature="Vd%2BJEb0KnUhEv1E1g3nf4Vl3SSM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1363100774", oauth_version="1.0"]、クエリ文字列を読み取ろうとするサービスhttp://myservice.mycompany.com?oauth_consumer_key=USER&oauth_nonce=4027096421883800497&oauth_signature=Vd%2BJEb0KnUhEv1E1g3nf4Vl3SSM%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1363100774&oauth_version=1.0

これに関する問題は、URL に署名してから HttpPost リクエストを作成しようとすると、URL が POST ではなく GET という接頭辞を持つベースストリングを取得し、サービスが計算した別の署名を与えることです。Signpost は何も悪いことをしていません。その URL 署名方法は、デフォルトで GET に設定されており、すぐに使用できる他の可能性はありません。これは、クエリ文字列ではなく、POST を実行するときにヘッダー パラメーターを読み取る必要があり (私の「同僚」の家を卵にする)、Signpost は、POST を実行するときに行う必要がある要求に署名するときにこれらを追加するためです。

Signingbasestring は、Signpost で生成される SigningBaseString クラス メソッドで確認できます。

解決

これが私が行った方法ですが、他の方法が可能であるか、さらに優れている可能性があります。

  1. 道しるべのソース コードを取得し、プロジェクトに追加します。ここで入手できます
  2. クラスを見つけてOAuthConsumer署名方法を変更し、リクエストが POST である必要があるという情報を渡すことができるようにします。私の場合、ブール値を次のように追加しましたpublic String sign(String url, boolean POST)
  3. ここで、クラスのsignメソッドを変更して拡張する必要があります。私の場合、ブール変数をメソッドに追加し、メソッド呼び出しの直前に次を追加しましたAbstractOAuthConsumerCommonsHttpOAuthConsumerDefaultOAuthConsumerif(POST) request.setMethod("POST");sign(request);
  4. 現在、リクエストは Signpost 固有のオブジェクトである HTTPRequest であるため、これはエラーをスローします。それを変更してメソッドを追加する必要がありますpublic void setMethod(String method);
  5. これにより、次のクラスHttpURLConnectionRequestAdapterHttpRequestAdapterおよびでエラーが発生しますUrlStringRequestAdapter。メソッドの実装をそれらすべてに追加する必要がありますが、フレーバーは異なります。最初に追加します

    public void setMethod(String method){
    try {
     this.connection.setRequestMethod(method);
     } catch (ProtocolException e) {
    
        e.printStackTrace();
     }
    }
    

    2番目に追加します

    public void setMethod(String method){
    
       try {
           RequestWrapper wrapper = new RequestWrapper(this.request);
           wrapper.setMethod(method);
           request = wrapper;
       } catch (org.apache.http.ProtocolException e) {
        e.printStackTrace();
        }   
    }
    

    そして最後に追加します

    public void setMethod(String method){
       mMethod = method;
    }
    

    私が使用して試したのは最初と最後だけであることに注意してください。しかし、これは少なくとも、私と同じ問題を抱えている場合、問題を解決する方法についてのアイデアを提供します.

とにかくこれが役立つことを願っています。

-Mr.ドレスデン

于 2013-03-12T15:46:00.183 に答える
4

oauth-signpostとを使用して POST リクエストに署名するHttpURLConnectionことは可能ですが、ちょっとしたハックが必要です。

秘訣は、POST パラメーターをパーセント エンコードし、 method を使用して OAuth ライブラリに追加することsetAdditionalParameters()です。

例については、この記事を参照してください。

于 2014-04-07T09:00:48.230 に答える