twitter4j 401身份验证错误持久存取AccessToken

时间:2013-05-24 14:58:17

标签: android authentication token twitter4j

我很难弄清楚发生了什么。我有一个典型的应用程序结构,它产生一个负责获取Twitter令牌的OAuthActivity,然后我的主应用程序活动将该令牌用于各种与Twitter相关的操作。

我的OAuthActivity有效。我获得了一个身份验证令牌,Twitter网页屏幕正确显示了我的应用程序名称等....此外,在该活动中,我可以发送推文并它会被发布。。这意味着OAuthActivity正常工作,时钟同步令牌有效等......

但是当这个OAuthActivity完成并返回到调用活动时,每当我尝试使用该标记(从持久密钥/密钥重新创建它)时,无论什么操作,操作总是失败了401,抱怨AuthChallenge报告为空...就像我提供了一个空令牌,但我没有 !!!

请附上我的OAuthActivity的来源,以及我如何在主要活动中初始化Twitter对象的来源。如果你看错了,请告诉我。

PD - 我显然已经检查过我分配的令牌值是否相同 !!还尝试了不同的方式来实例化Twitter,通过属性,通过构建器,通过集......并且没有任何变化:(

编辑 - >我发现我必须在新的Twitter对象上调用“ verifyCredentials()”,如果我想重用一个令牌,但是......没有运气! (请在最后找到发布的例外情况)

EDIT-2 - ;如果我同时使用子活动和父级

mTwitter=TwitterFactory.getSingleton()

然后twitter对象起作用,但这对我来说并不是真的可以接受,因为它不使用持久性,我需要每次都授权应用程序。此外,只有Twitter对象被授权,TwitterStream不断抛出异常。

干杯!

父活动的源代码,我尝试使用在子活动中获得的访问令牌,如下所示。无论我尝试用这个令牌做什么总是得到401。

private void init_twitter(String tok, String sec) {

    ConfigurationBuilder cb = new ConfigurationBuilder();

    cb.setDebugEnabled(true)
      .setOAuthConsumerKey(Conf.OAUTH_CONSUMER_KEY)
      .setOAuthConsumerSecret(Conf.OAUTH_CONSUMER_SECRET)
      .setOAuthAccessToken(tok)
      .setOAuthAccessTokenSecret(sec);

    TwitterFactory tf = new TwitterFactory(cb.build());

    mTwitter=tf.getInstance();



    /** This always fails, even though I call this routine with the 
                correct token & secret !!! See at the enf of message for an alternate 
                routine like this one that makes use of verifyCredentials and
                also fails. */ 

    new Thread(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                mTwitter.updateStatus("yello 2");
            } catch (TwitterException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }}).start();


}

孩子OAuthActivity的SOURce代码,它显然可以正常工作,因为我获得了访问令牌&我能发推文:

import a lot;

public class TwitterLogin extends Activity {

    private final String TAG = "TwitterLogin";
    public final static String PREF_KEY_OAUTH_TOKEN="twitter.oauth.token", PREF_KEY_OAUTH_SECRET="twitter.oauth.secret", PREF_KEY_TWITTER_LOGIN="twitter.oauth.login";

    private SharedPreferences mPreferences;

    private Twitter twitter = new TwitterFactory().getInstance();


    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "Starting task to retrieve request token.");
        this.mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        super.onCreate(savedInstanceState);
        getActionBar().setTitle("TWITTER AUTHENTICATION");


    }

    private void returnParent(boolean result)  {
        setResult(result?Activity.RESULT_OK:Activity.RESULT_CANCELED, null);
        if (Conf.LOG_ON) Log.d(TAG, "TWITTER AUTH: END PROCESS , GLOBAL RESULT "+result);

        /** THE FOLLOWING THING WORKS !!!!! IT SUCCESSFULLY TWEETS */

        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    twitter.updateStatus("yello");
                } catch (TwitterException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }}).start();



        finish();
    }

    /**
     * Uses TWITTER4J to get the Request URL. It gets something like 
     * AUTH URL TWITTER4J IS http://api.twitter.com/oauth/authorize?oauth_token=xxxxxxxxxxxxxxxxxxxxx
     *
     * @return The Request URL to open in webview and get the Verifier
     */

    private String oauth_twitter4j_getRequestUrl() throws TwitterException {
        twitter.setOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
        RequestToken tempToken = twitter.getOAuthRequestToken(Constants.OAUTH_CALLBACK_URL);
        return tempToken.getAuthorizationURL();
    }


    @Override
    protected void onResume() {
        super.onResume();
        WebView webview = new WebView(this);
        webview.getSettings().setJavaScriptEnabled(true);  
        webview.setVisibility(View.VISIBLE);
        setContentView(webview);

        Log.i(TAG, "Retrieving request token from Google servers");

        try {

            StrictMode.ThreadPolicy policy = new StrictMode. ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);

            String authorizationUrl=oauth_twitter4j_getRequestUrl();
            Log.d(TAG, "AUTH URL TWITTER4J IS "+authorizationUrl_t);

            webview.setWebViewClient(new WebViewClient() {  

                @Override
                public boolean shouldOverrideUrlLoading(WebView webView, String url) { 
                    if (Conf.LOG_ON) Log.d(TAG,"WebView: "+url);
                    if (url != null && url.startsWith(Constants.OAUTH_CALLBACK_URL)) try {
                        System.out.println("TWEET TWEET TWEET");
                        retrieveAccessToken(url); //added this
                        webView.setVisibility(View.GONE); //added this
                        return true;            
                    } catch (Exception e) {
                        e.printStackTrace();
                        returnParent(false);
                        return true;
                    } else return false;
                }

                private void saveAccessToken(AccessToken accessToken) {

                    // Shared Preferences
                    Editor e = mPreferences.edit();

                    // After getting access token, access token secret
                    // store them in application preferences

                    e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
                    e.putString(PREF_KEY_OAUTH_SECRET,accessToken.getTokenSecret());
                    e.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
                    e.commit(); 

                    Log.e("Twitter OAuth Token", "> " + accessToken.getToken()+"-"+accessToken.getScreenName());

                }

                private void retrieveAccessToken(String url) throws Exception {
                    String requestToken  = extractParamFromUrl(url,"oauth_token");
                    String verifier= extractParamFromUrl(url,"oauth_verifier");
                    if (Conf.LOG_ON) Log.d(TAG, "Tenemos ACCESS TOKEN y VERIFIER :"+requestToken+","+verifier+","+(new Date().toString()));

                    if (ONLY_TWITTER4J)
                        retrieveAccessToken_with4j(verifier);
                    else
                        retrieveAccessToken_signpost(verifier);
                }

                private void retrieveAccessToken_with4j(String verifier) throws TwitterException {
                    AccessToken a=twitter.getOAuthAccessToken(verifier);
                    saveAccessToken(a);
                    returnParent(true);
                }

                private String extractParamFromUrl(String url,String paramName) {
                    String queryString = url.substring(url.indexOf("?", 0)+1,url.length());
                    QueryStringParser queryStringParser = new QueryStringParser(queryString);
                    return queryStringParser.getQueryParamValue(paramName);
                }  

            });  

            webview.loadUrl(authorizationUrl);  
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

使用我确定正确的令牌调用VerifyCredentials时得到的异常:

    Received authentication challenge is null
    W/System.err(24915): Relevant discussions can be found on the Internet at:
    W/System.err(24915):    http://www.google.co.jp/search?q=6f0f59ca or
    W/System.err(24915):    http://www.google.co.jp/search?q=20d0f74e
    W/System.err(24915): TwitterException{exceptionCode=[6f0f59ca-20d0f74e 1de2170b-f94dee38], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=3.0.3}
    W/System.err(24915):    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:192)
    W/System.err(24915):    at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:61)
    W/System.err(24915):    at twitter4j.internal.http.HttpClientWrapper.get(HttpClientWrapper.java:89)
    W/System.err(24915):    at twitter4j.TwitterBaseImpl.fillInIDAndScreenName(TwitterBaseImpl.java:126)
    W/System.err(24915):    at twitter4j.TwitterImpl.verifyCredentials(TwitterImpl.java:592)
    W/System.err(24915):    at com.regaliz.helpers.TwitterManager$2.run(TwitterManager.java:140)
    W/System.err(24915):    at java.lang.Thread.run(Thread.java:856)
    W/System.err(24915): Caused by: java.io.IOException: Received authentication challenge is null
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:397)
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.processResponseHeaders(HttpURLConnectionImpl.java:345)
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:276)
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:479)
    W/System.err(24915):    at twitter4j.internal.http.HttpResponseImpl.<init>(HttpResponseImpl.java:34)
    W/System.err(24915):    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:156)
    W/System.err(24915):    ... 6 more

这是为了使用verifyCredentials而修改的函数:

    private void init_twitter_2(final String tok, final String sec) throws TwitterException {

            ConfigurationBuilder cb = new ConfigurationBuilder();

            cb.setDebugEnabled(true)
              .setOAuthConsumerKey(Conf.OAUTH_CONSUMER_KEY)
              .setOAuthConsumerSecret(Conf.OAUTH_CONSUMER_SECRET);
    //        .setOAuthAccessToken(tok)
    //        .setOAuthAccessTokenSecret(sec);

            TwitterFactory tf = new TwitterFactory(cb.build());

            mTwitter=tf.getInstance();
            Log.d(TAG, "init_twitter_2 "+tok+","+sec);
            new Thread(new Runnable(){

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    User u;
                    try {
                        /** also tried setting token&secret like this, instead of in the builder-->no success */
                        mTwitter.setOAuthAccessToken(new AccessToken(tok,sec));
                        u = mTwitter.verifyCredentials();
                        Log.d(TAG, "User: "+u.getName());

                    } catch (TwitterException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }}).start();


        }

1 个答案:

答案 0 :(得分:5)

有愚蠢的人,愚蠢的人,愚蠢的人,然后就是我。一个星期以来,我一直在努力寻找代码,追踪Twitter4j,用卷曲复制oauths,怀疑垃圾收集活动,追踪DDMS,计算令牌上的哈希......只是发现我有2个Conf.OAUTH_CONSUMER_xxxxx实例不同的价值观

由于这些东西来自常数,名字相似,我没有意识到。

叹息 - 50个声望指向厕所!