【问题标题】:Creating a Signature for Oauth with Twitter使用 Twitter 为 Oauth 创建签名
【发布时间】:2020-10-02 12:25:23
【问题描述】:

我想使用 twitter API https://api.twitter.com/1.1/statuses/user_timeline.json 创建一个 Oauth。 我已经收集了一些 Java 代码,并且能够在 twitter 示例 Twitter Oath Example

中重现签名

我的问题。 我的 URL 还包含一些额外的参数,我不确定如何在 %encoded 字符串中表示这些参数。
这是我目前拥有的。

Method: "GET"
URL: "https://api.twitter.com/1.1/statuses/user_timeline.json
Parameters: "screen_name=user handle"
CONSUMER_API_KEY = "oauth_consumer_key=gdprVZGNotRealKeyZRGMUfP";
OAUTH_NONCE = "oauth_nonce=u4cknC6Lfea";
HMACSHA1 ="oauth_signature_method=HMAC-SHA1";
OAUTH_TIMESTAMP = "oauth_timestamp=1591889894";
ACCESS_TOKEN = "oauth_token=63345074-vNvsSSlMsMmNotRealKeytGR040GD9";
oauth_version ="oauth_version=1.0";
public class MainActivity extends AppCompatActivity {
    private ArrayList<MyTweet> tweets = new ArrayList<MyTweet>();
    private TextView post_reponse_text;
    private MyTweetsAdapter Adapter;
    Twitter twitter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button post_request_button = findViewById(R.id.test);
        post_reponse_text = findViewById(R.id.get_response_data);
        post_request_button.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.O)
            @Override
            public void onClick(View v) {
                postRequest();
                String url = "https://api.twitter.com/1.1/statuses/user_timeline.json";

                 test t1 = new test();
                 //t1.concatURL(url,"GET");
                 //String percented = t1.encode(url);

                String percentURL1 = t1.encode(url);
                Log.v("String encoded with ent",percentURL1);

                Log.v("Concat:",t1.StringConcat());
                String fin = t1.concatURL(percentURL1,"GET") + t1.encode(t1.StringConcat());


                Log.v("FinishedString:",fin);


                Log.v("Sig:",t1.generateSignature(fin, "CONSUMERSECREATrFMeKkS", "TOKENSECREATvqWFWzxEZtGdc"));

            }
        });
    }

    private void postRequest() {
        RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
        String url = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=user handle";
        final StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.e("HttpClient", "success! response: " + response.toString());
                        try {
                            // post_reponse_text.setText("Post Data : " + response);
                            post_reponse_text.setText("Twitter Feed");
                            JSONArray jsonArray = new JSONArray(response);

                            for (int i = 0; i < jsonArray.length(); i++) {
                                JSONObject session = jsonArray.getJSONObject(i);

                                MyTweet tweet = new MyTweet("might need to remove", "this also");
                                tweet.content = session.getString("text");
                                tweet.author = session.getString("id_str");
                                tweets.add(tweet);
                            }

                            /*Send to Adapter*/
                            RecyclerView recyclerView = findViewById(R.id.my_recycler_view);
                            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
                            recyclerView.setLayoutManager(layoutManager);
                            Adapter = new MyTweetsAdapter(tweets);
                            recyclerView.setAdapter(Adapter);
                            Adapter.setOnItemClickListener(new MyTweetsAdapter.OnItemClickListener() {
                                @Override
                                public void onItemClick(int position) {

                                }
                            });

                        } catch (Exception e) {
                            e.printStackTrace();
                            Log.v("Error:", "Error Creating JSON object");
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                error.printStackTrace();
                Log.e("HttpClient", "error: " + error.toString());
                post_reponse_text.setText("Failed to find Twitter feed");

            }
        })
        {

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();

//Generated from postman and added manually
                params.put("Authorization", "OAuth oauth_consumer_key=\"notrealkeyZRGMUfP\",oauth_token=\"63139074-vNvsSSnotrealkey\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1592143976\",oauth_nonce=\"i5Ha2524SuC\",oauth_signature=\"DFf7rD9enXp1pIxsCkf99VC4rSE%3D\"");

                return params;
            }
        };
        queue.add(stringRequest);
    }
}

公开课测试{

//http://optimumbrew.com/blog/2015/03/oauth/how-to-generate-oauth-signature-for-twitter-in-core-java

//used to % encode string values
@RequiresApi(api = Build.VERSION_CODES.O)
public String encode(String value) {
    String encoded = "";
    try {
        encoded = URLEncoder.encode(value, "UTF-8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    String sb = "";
    char focus;
    for (int i = 0; i < encoded.length(); i++) {
        focus = encoded.charAt(i);
        if (focus == '*') {
            sb += "%2A";
        } else if (focus == '+') {
            sb += "%20";
        } else if (focus == '%' && i + 1 < encoded.length()
                && encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
            sb += '~';
            i += 2;
        } else {
            sb += focus;
        }
    }
    Log.v("String Encoded:", sb);



    return sb;

}


//passes the string with consumer secret & token to generate a signature.
//I will send this signature in the header requests
@RequiresApi(api = Build.VERSION_CODES.O)
public String generateSignature(String signatueBaseStr, String oAuthConsumerSecret, String oAuthTokenSecret) {
    byte[] byteHMAC = null;
    try {
        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec spec;
        if (null == oAuthTokenSecret) {
            String signingKey = encode(oAuthConsumerSecret) + '&';
            spec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");
        } else {
            String signingKey = encode(oAuthConsumerSecret) + '&' + encode(oAuthTokenSecret);
            spec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");
        }
        mac.init(spec);
        byteHMAC = mac.doFinal(signatueBaseStr.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return twitter4j.BASE64Encoder.encode(byteHMAC);
    // return new twitter4j.BASE64Encoder().encode(byteHMAC);
}

public String concatURL(String url, String method) {

    String contact = method + "&" + url+"&";
    return contact;
}


@RequiresApi(api = Build.VERSION_CODES.O)
public String StringConcat() {

   String CONSUMER_API_KEY = "oauth_consumer_key=gdnotrealkeyRGMUfP";
    String OAUTH_NONCE = "oauth_nonce=i5Ha2524SuC";
    String HMACSHA1 ="oauth_signature_method=HMAC-SHA1";
    String OAUTH_TIMESTAMP = "oauth_timestamp=1592143976";
    String ACCESS_TOKEN = "oauth_token=63139074-vNvnotrealkeygJn8VtGR040GD9";
    String oauth_version ="oauth_version=1.0";
    String screen_name = "screen_name=user handle";

            /*
            oauth_consumer_key=\"gdprVZGkHT7mOfALr8ZRGMUfP\",
            oauth_nonce=\"u4cknC6Lfea\",
            oauth_signature_method=\"HMAC-SHA1\",
            oauth_timestamp=\"1591889894\",
            oauth_token=\"63139074-vNvsSSlMsMmosQwJ2EWVmHvGzAlgJn8VtGR040GD9\"
             */


    String concat = CONSUMER_API_KEY+ "&" +OAUTH_NONCE+ "&" +HMACSHA1+ "&" +OAUTH_TIMESTAMP+ "&" +ACCESS_TOKEN+ "&" +oauth_version+ "&"+screen_name;
    //String concat = CONSUMER_API_KEY+ "&" +OAUTH_NONCE+ "&" +HMACSHA1+ "&" +OAUTH_TIMESTAMP+ "&" +ACCESS_TOKEN+ "&" +oauth_version;
    return concat;
}

}





Combining to make
GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fuser_timeline.json&oauth_consumer_key%3DgdprVZGNotRealKeyZRGMUfP%26oauth_nonce%3Du4cknC6Lfea%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1591889894%26oauth_token%3D63345074-vNvsSSlMsMmNotRealKeytGR040GD9%26oauth_version%3D1.0%26screen_name%3Duser%20handle
Using postman I can get instances of successful auths and can see the created signature of those auths. Using the timestamps and nonces from postman I am trying to validate I can create the same signature as postman. So far I'm unsuccessful and I'm assuming its something to do with how i put the string together

【问题讨论】:

标签: java twitter oauth postman twitter-oauth


【解决方案1】:

请求中似乎缺少实际签名

您可以在此链接中找到更多信息

https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/creating-a-signature

如果您遇到困难,请回电,我会帮助您

【讨论】:

  • 谢谢,非常感谢。因此,如果我使用 Postman,我可以发送我的消费者密钥、访问令牌、消费者秘密和令牌秘密。 Postman 然后通过自动添加随机数、时间戳和签名类型来生成签名。然后我可以看到返回的签名值。我试图通过 Java 模拟的是从邮递员添加相同的详细信息并创建相同的签名结果。我已经按照你提供的链接中的步骤进行操作,但我没有得到相同的结果。所以我假设我没有正确地将字符串放在一起以生成相同的 Post man 结果
  • 所以我想我的问题是,Given Method: "GET" URL: "api.twitter.com/1.1/statuses/user_timeline.json?"参数:"screen_name=用户句柄" CONSUMER_API_KEY = "oauth_consumer_key=gdprVZGNotRealKeyZRGMUfP"; OAUTH_NONCE = "oauth_nonce=u4cknC6Lfea"; HMACSHA1 =“oauth_signature_method=HMAC-SHA1”; OAUTH_TIMESTAMP = "oauth_timestamp=1591889894"; ACCESS_TOKEN = "oauth_token=63345074-vNvsSSlMsMmNotRealKeytGR040GD9"; oauth_version="oauth_version=1.0";在通过base64编码传递之前,字符串应该是什么格式?
  • 仍然不清楚,使用 HMac-SHA1 和密钥签名后必须使用 base64。这个过程有点复杂,所以你必须在这里提供一些代码,以便我可以参考并提供响应
  • 添加了代码。我使用方法 generateSignature() 来传递生成的字符串以及 AuthConsumerSecret 和 oAuthTokenSecret。我相信这是可行的,因为我能够使用 twitter 示例对其进行测试。我认为错误的是我构建的要传递给方法并生成签名的字符串。
  • 是的,那是通常的嫌疑人,您是否尝试过 Pathfix,如果您正在为许多提供商构建基于 OAuth 的集成,则会有所帮助
猜你喜欢
  • 2011-03-27
  • 2014-09-11
  • 2012-09-10
  • 2014-04-07
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多