0

过去一天我一直在努力为我的 android 应用程序实现 OAuth。我遇到了一个又一个问题。我只想签署一个请求,将其发送到 Web 服务并得到响应(我相信这是两条腿的方法)。

我已经下载了路标:

-signpost-core-1.2.1.2

-signpost-commonshttp4-1.2.1.2

我已将 jar 添加到我的库构建路径中。

是否有特定的地方我需要放置这些 jar 文件才能使它们工作?

我遇到最大麻烦的部分是生成签名并最终签署请求。HttpParemeters 不断出现错误。

有没有办法让我以编程方式生成 baseString ?

有人可以指导我使用一个有效的两条腿 Oauth android 特定示例吗?

我的代码如下:

public void excecuteSigning(String targetURL){
        String SOAP_ACTION = "http://amebatv.com/api/authDevice";
        System.setProperty("http.keepAlive", "false");      
        HttpURLConnection _request = null;  
        DefaultHttpClient httpclient = null;

    try{ 

        CONSUMER_SECRET  = app_pref.getString("consumerSecret", "");
        CONSUMER_KEY = app_pref.getString("consumerKey", "");   
        String oaut_token = app_pref.getString("accessToken", "");
        String tokenSecret = app_pref.getString("tokenSecret", "");
        String deviceId = deviceInfo.getSerial();


        CommonsHttpOAuthConsumer  consumer = new CommonsHttpOAuthConsumer (CONSUMER_KEY,CONSUMER_SECRET);
        consumer.setTokenWithSecret(oaut_token, tokenSecret); 

        //HttpRequest request;
        HttpParameters requestParameters = new HttpParameters();
        requestParameters.put("file", "vacation.jpg");
        requestParameters.put(OAuth.OAUTH_CONSUMER_KEY, "dpf43f3p2l4k3l03");
        requestParameters.put(OAuth.OAUTH_NONCE, "kllo9940pd9333jh");
        requestParameters.put(OAuth.OAUTH_SIGNATURE_METHOD, "HMAC-SHA1");
        requestParameters.put(OAuth.OAUTH_TIMESTAMP, "1191242096");
        requestParameters.put(OAuth.OAUTH_TOKEN, "nnch734d00sl2jdk");
        requestParameters.put(OAuth.OAUTH_VERSION, "1.0");
        requestParameters.put("size", "original");


        HttpPost request = new HttpPost(targetURL);
        SignatureBaseString baseString = new SignatureBaseString((HttpRequest) request, requestParameters);

        String base = baseString.generate();
        System.out.println(":"+base);

        System.out.println(computeHmac(base,"kd94hf93k423kf44&pfkkdhi9sl3r4s00"));

       httpclient = new DefaultHttpClient();

        ContentProducer cp = new ContentProducer() {
            public void writeTo(OutputStream outstream) throws IOException {
                Writer writer = new OutputStreamWriter(outstream, "UTF-8");
                writeXml(writer);
            }
        };

       HttpParameters params = new HttpParameters();
       HttpEntity entity = new EntityTemplate(cp);
       HttpPost request = new HttpPost(targetURL);         

       request.addHeader("Authorization",AUTH_HEADER);
       request.addHeader("Content-Type", "text/xml; charset=utf-8");
       //request.addHeader("Content-Length",""+soapXML.getBytes().length);
       request.addHeader("SOAPAction",SOAP_ACTION);
       request.setEntity(entity);

        // sign the request
        consumer.sign(request);
        // send the request
        //request.connect();
        HttpResponse response = httpclient.execute(request);

        //get response               
        //StringBuffer response = new StringBuffer();
        InputStream instream = null;    
        BufferedReader br = null;        
         try{            
             int respcode = response.getStatusLine().getStatusCode();
             Log.i("Server Response", ""+respcode);

             //get XML from InputStream
            if(respcode>= 200){ 
                instream =  response.getEntity().getContent();                  
                client.buildDoc(instream);      
            }
            else{
                Log.i("Server Response", ""+respcode);
                //instream = request.getErrorStream();
                }

        }catch(Exception e){
            Log.i("SPLASH","Unable to create connection stream");
            e.printStackTrace();
        }
         finally {      
          if(instream != null) {
            Log.i("SPLASH","Disconnecting stream");
            instream.close();
          }
         }
             */
    }
    catch(Exception e){
        Log.i("SPLASH","Unable to create connection");
        e.printStackTrace();
    }finally {      
          if(httpclient != null) {
            Log.i("SPLASH","Disconnecting");
            httpclient.getConnectionManager().shutdown();
          }
    }
}

/*
 * Method:computeHmac()
 * @params: String, String
 * return: String 
 */
public String computeHmac(String baseString, String key)
                                throws NoSuchAlgorithmException, 
                                InvalidKeyException, 
                                IllegalStateException, 
                                UnsupportedEncodingException
    {

        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec secret = new SecretKeySpec(key.getBytes(), mac.getAlgorithm());
        mac.init(secret);
        byte[] digest = mac.doFinal(baseString.getBytes());
        return Base64.encodeToString(digest,Base64.URL_SAFE);
    }
4

2 回答 2

1

我从来没有使用过路标,所以我无法帮助你。我只能分享一些我为做 oauth dance 而编写的代码。我使用 scribe,它适用于 1.0 和 2.0 oauth 规范。我的 web 服务需要通过 webbrowser 进行身份验证,使用 webview 可以正常工作。下面的代码可能无法编译,但它来自一个工作(但仍在开发中)的应用程序。由于我仍在学习android,欢迎所有评论和更正。

整个过程从我用于与 web 服务通信的活动开始,它只包含最初隐藏的 webview。Init 方法是一切开始的地方:

    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;

    import org.scribe.builder.ServiceBuilder;
    import org.scribe.builder.api.DefaultApi10a;
    import org.scribe.model.OAuthRequest;
    import org.scribe.model.Response;
    import org.scribe.model.Token;
    import org.scribe.model.Verb;
    import org.scribe.model.Verifier;
    import org.scribe.oauth.OAuthService;

    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.View;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;

    public class FCEHttpHelper {
        public static final String LOG_TAG = FCEHttpHelper.class.getSimpleName(); 

      //api_key/oauth_key
      //string that is given to you by webservice provider to uniquely identify your app
        final static String APIKEY = "xxxxxx"; 

      //oauth_secret
      //also given to you by service provider
        final static String APISECRET = "yyyyyyy";

      //callback sent to webview after authorization
      //some services allow you to set it up manually, ie. Quizlet
        final static String CALLBACK = "oauth://flashcardexchange";

      //scribe classes
        Token token;
        OAuthService serviceBuilder;

        static class GetUrl extends AsyncTask<String, Integer, String> {
            public Token t;
            public OAuthService serviceBuilder;
            public Activity act;
            public Handler handler;

            protected String doInBackground(String... urls) {           
                String resp = "";

                if (t != null) {
                    OAuthRequest req = new OAuthRequest(Verb.GET, urls[0]);
                    serviceBuilder.signRequest(t, req);
                    Response response = req.send();
                    resp = response.getBody();
                }
                else {
                    URL url = null;
                    try {
                        url = new URL(urls[0]);
                    } catch (MalformedURLException e) {
                        Log.d(LOG_TAG, e.getMessage());
                    }

                    HttpURLConnection urlConnect = null;
                    try {
                        urlConnect = (HttpURLConnection) url.openConnection();
                        resp = StringUtils.convertStreamToString(urlConnect
                                .getInputStream());

                    } catch (Exception e) {
                        Log.d("RESP", "URL ex", e);
                    } finally {
                        if (urlConnect != null)
                            urlConnect.disconnect();
                    }
                }
                return resp;
            }

            protected void onProgressUpdate(Integer... progress) {
            }

            protected void onPostExecute(String result) {
                //Log.i(LOG_TAG, result);
                Intent data = new Intent();
                Bundle extras = new Bundle();
                extras.putString("RESULT", result);
                data.putExtras(extras);
                act.setResult(Activity.RESULT_OK, data);
                act.finish();
            }
        }

        @Override
        public void Destroy() {
        }

        @Override
        public void Init(final Activity act, final WebView webView, boolean oauthRequired, final Handler handler) {
            Intent intent = act.getIntent();
            final String surl = intent.getStringExtra(INTENT_URL);

            if ( !oauthRequired ) {
                GetUrl gurl = new GetUrl();
                gurl.t = null;
                gurl.serviceBuilder = null;
                gurl.act = act;
                gurl.handler = handler;
                gurl.execute(surl);         
                return;
            }

            // get saved token from database, if it does not exists then web authentication is required

            // set up service and get request token as seen on scribe website
            // https://github.com/fernandezpablo85/scribe-java/wiki/Getting-Started
            serviceBuilder = new ServiceBuilder()
                    .provider(new DefaultApi10a() {

              /// example is for flashcardexchange oauth

                        @Override
                        public String getRequestTokenEndpoint() {
                            return "https://secure.flashcardexchange.com/oauth_request_token";
                        }

                        @Override
                        public String getAccessTokenEndpoint() {
                            return "https://secure.flashcardexchange.com/oauth_access_token";
                        }

                        @Override
                        public String getAuthorizationUrl(
                                org.scribe.model.Token requestToken) {
                            return "https://secure.flashcardexchange.com/oauth_login"
                                    + "?oauth_token=" + requestToken.getToken();
                        }
                    }).apiKey(APIKEY).apiSecret(APISECRET).callback(CALLBACK)
                    .debug()
                    .build();

            if (token == null) {

                Message msg = new Message();
                msg.what=1;
                handler.sendMessage(msg);

                webView.setVisibility(View.VISIBLE);

                final Token requestToken = serviceBuilder.getRequestToken();
                final String authURL = serviceBuilder
                        .getAuthorizationUrl(requestToken);

                // attach WebViewClient to intercept the callback url
                webView.setWebViewClient(new WebViewClient() {

                    @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {

                        // check for our custom callback protocol
                        // otherwise use default behavior
                        if (url.startsWith("oauth")) {
                            // authorization complete hide webview for now.
                            webView.setVisibility(View.GONE);

                            Uri uri = Uri.parse(url);
                            String verifier = uri
                                    .getQueryParameter("oauth_verifier");
                            Verifier v = new Verifier(verifier);

                            // save this token for practical use.
                            Token accessToken = serviceBuilder.getAccessToken(
                                    requestToken, v);

                            // host oauth detected from callback
                            // oauth://flashcardexchange
                            if (uri.getHost().equals("flashcardexchange")) {

                                // save accessToken to database to use it later

                                webView.setVisibility(View.GONE);

                                Message msg = new Message();
                                msg.what=2;
                                handler.sendMessage(msg);

                                GetUrl gurl = new GetUrl();
                                gurl.t = accessToken;
                                gurl.act = act;
                                gurl.handler = handler;
                                gurl.serviceBuilder = serviceBuilder;
                                gurl.execute(surl);                         
                            }

                            return true;
                        }

                        return super.shouldOverrideUrlLoading(view, url);
                    }
                });

                // send user to authentication page
                webView.loadUrl(authURL);
            } else {
                webView.setVisibility(View.GONE);

                GetUrl gurl = new GetUrl();
                gurl.t = token;
                gurl.serviceBuilder = serviceBuilder;
                gurl.act = act;
                gurl.handler = handler;
                gurl.execute(surl);
            }       
        }   
    }
于 2012-04-15T19:05:17.200 回答
1

库需要位于 libs 文件夹中(带有 s!),然后它们会自动添加到项目的构建路径中。

于 2012-04-15T19:38:26.727 回答