Twitter Oauth 1.0请求与驼峰路线

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Twitter Oauth 1.0请求与驼峰路线相关的知识,希望对你有一定的参考价值。

我需要创建一个camel路由,它将Rest请求发送到Twitter API。我知道有可能使用twitter组件,但在我的情况下,我需要使用http4组件发出Http请求。由于这个组件没有OOTB对Oauth的支持,我创建了以下处理器,以便根据twitter文档https://dev.twitter.com/oauth/overview/creating-signatures创建必要的头文件,但我得到错误响应,我不明白我做错了什么:

@Override
public void process(Exchange exchange) throws Exception {


    int millis = (int) System.currentTimeMillis() * -1;
    int time = (int) millis / 1000;

    /**
     * Listing of all parameters necessary to retrieve a token
     * (sorted lexicographically as demanded)
     */
    String[][] data = {
            {"oauth_consumer_key", "<consumer_key>"},
            {"oauth_nonce",  String.valueOf(millis)},
            {"oauth_signature", ""},
            {"oauth_signature_method", "HMAC-SHA1"},
            {"oauth_timestamp", String.valueOf(time)},
            {"oauth_token", "<token>"},
            {"oauth_version", "1.0"}
    };

    HttpMethods methodObject = exchange.getIn().getHeader(Exchange.HTTP_METHOD, HttpMethods.class);
    String method = methodObject.toString();
    String uri = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class);
    String path = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class);
    String query = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class);

    String url = uri;
    if (path!=null){
        url += path;
    }


    LOGGER.info("URL= "+url);

    /**
     * Generation of the signature base string
     */
    String signature_base_string =
            method+"&"+ URLEncoder.encode(url, "UTF-8")+"&";
    signature_base_string+=URLEncoder.encode(query, "UTF-8") + "%26";

    LOGGER.info("signature_base_string= "+signature_base_string);


    for(int i = 0; i < data.length; i++) {
        // ignore the empty oauth_signature field
        String additional ="";
        if(i != 2) {
            additional = URLEncoder.encode(data[i][0], "UTF-8") + "%3D" +
                    URLEncoder.encode(data[i][1], "UTF-8") ;

            if (i!= data.length-1){
                additional += "%26";
            }

            signature_base_string += additional;
            LOGGER.info("signature_base_string-Additional= "+additional);
        }

    }

    /**
     * Sign the request
     */
    Mac m = Mac.getInstance("HmacSHA1");
    m.init(new SecretKeySpec(("<consumer_secret>&<token_secrer>").getBytes(), "HmacSHA1"));
    m.update(signature_base_string.getBytes());
    byte[] res = m.doFinal();
    String sig = String.valueOf(new BASE64Encoder().encode(res));
    data[2][1] = sig;

    /**
     * Create the header for the request
     */
    String header = "OAuth ";
    for(String[] item : data) {
        header += item[0]+"=""+item[1]+"", ";
    }
    // cut off last appended comma
    header = header.substring(0, header.length()-2);

    String charset = "UTF-8";
    exchange.getIn().setHeader("Authorization", header);
    exchange.getIn().setHeader("Accept-Charset", charset);

}

路线很简单:

    <route id="download-twetts">
        <from uri="direct:download-twetts"/>
        <setHeader headerName="CamelHttpUri">
            <constant>https://api.twitter.com</constant>
        </setHeader>
        <setHeader headerName="CamelHttpMethod">
            <constant>GET</constant>
        </setHeader>
        <setHeader headerName="CamelHttpPath">
            <constant>/1.1/search/tweets.json</constant>
        </setHeader>
        <setHeader headerName="CamelHttpQuery">
            <constant>q=test</constant>
        </setHeader>
        <process ref="oauthHeaderProcessor"/>
        <to uri="http4://twitter-search-tweets?throwExceptionOnFailure=false"/>
        <to uri="log:INFO?showHeaders=true"/>
        <log message="${body}"/>
        <to uri="mock:result"/>
    </route>

对请求的响应是400 http状态和响应正文:

{"errors":[{"code":215,"message":"Bad Authentication data."}]}
答案

作为解决方案,不是在camel-http4组件上进行中继,而是通过Scribe库实现oauth,可作为camel处理器使用。这里是:

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.scribe.oauth.OAuthService;
import org.scribe.builder.ServiceBuilder;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.SignatureType;
import org.scribe.model.Token;
import org.scribe.model.Verb;

public class OAuth10a implements Processor{

@Override
public void process(Exchange exchange) throws Exception {

    OAuthService service = new ServiceBuilder().provider(OneLeggedApi10.class)
        .apiKey(exchange.getProperty("target_key", String.class))                
        .apiSecret(exchange.getProperty("target_secret", String.class)) 
        /*.debugStream(System.out).*/
        .signatureType(SignatureType.QueryString)
        /*.scope("*").*/
        .build();

    String Url = exchange.getIn().getHeader("CamelHttpUri", String.class);
    String Method = exchange.getIn().getHeader("CamelHttpMethod", String.class);

    OAuthRequest request = null;
    if (Method.equals("GET")) {
        request = new OAuthRequest(Verb.GET, Url);
    } else {

        if (Method.equals("POST")) { request = new OAuthRequest(Verb.POST, Url); }
        if (Method.equals("PUT")) { request = new OAuthRequest(Verb.PUT, Url); }

        String payload = exchange.getIn().getBody(String.class);
        request.addPayload(payload);
        request.addHeader("Content-Type", "application/json;charset=UTF-8");
    }

    service.signRequest(new Token("", ""), request);
    Response response = request.send();

    exchange.setOut(exchange.getIn());
    exchange.getOut().setBody(response.getBody());
}
}

在你的蓝图camel上下文中,你只需要以这种方式调用它:

     <bean id="oauth10a" class="net.monstock.msc.config.common.OAuth10a"/>
 ...
 <camelContext ...
      <route ...
           <setProperty propertyName="target_key"><constant>KJFDFGHJKL</constant></setProperty>
           <setProperty propertyName="target_secret"><constant>kjhgfdertyuiolkjhgfrtyu</constant></setProperty>

           <setHeader headerName="CamelHttpMethod"><constant>POST</constant></setHeader>
           <setHeader headerName="CamelHttpUri"><simple>http://your.service.url/point</simple></setHeader>
           <process ref="oauth10a"/>

针对Woocommerce API进行测试和验证。

以上是关于Twitter Oauth 1.0请求与驼峰路线的主要内容,如果未能解决你的问题,请参考以下文章

将Zend_Service_Twitter_Search与经过身份验证的请求一起使用

Twitter API oauth/请求令牌页面不存在

twitteR R包OAuth问题:registerTwitterOAuth(cred)中的错误:oauth参数必须是OAuth类

另一个失败的 twitter oAuth cURL 访问令牌请求

Twitter oauth with flask_oauthlib,无法生成请求令牌

使用带有 RSA-SHA1 的 Twitter joauth 验证 OAuth1a 签名请求?