【问题标题】:How to implement OAuth 1.0a using retrofit for woocommerce Api in Android如何在 Android 中使用改造 woocommerce Api 来实现 OAuth 1.0a
【发布时间】:2017-02-17 20:16:30
【问题描述】:

我目前正在开发 woocommerce api,我需要使用改造来集成 api。该网站位于 HTTP 中,因此无法通过普通 HTTP 使用 HTTP 基本身份验证,因为密钥容易被拦截。 API 使用 OAuth 1.0a “单腿”身份验证来确保您的 API 密钥不会被截获。我已经通过 this artical 了解在 http 上使用哪种 OAuth 方法。

我已经使用Scribe 成功实现了 api,但我想使用改造来实现 api,在谷歌搜索后我发现拦截器是 Jake Wharton Oauth1SigningInterceptor

所以我在改造身份验证时实现了它,但 api 调用返回

{"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}

如果我使用 Scribe 调用相同的 api,则返回成功的响应

下面是我如何调用 Api

BasicAuthInterceptor.java(改编自杰克沃顿 Oauth1SigningInterceptor)

public class BasicAuthInterceptor implements Interceptor {
private static final Escaper ESCAPER = UrlEscapers.urlFormParameterEscaper();
private static final String OAUTH_CONSUMER_KEY = "oauth_consumer_key";
private static final String OAUTH_NONCE = "oauth_nonce";
private static final String OAUTH_SIGNATURE = "oauth_signature";
private static final String OAUTH_SIGNATURE_METHOD = "oauth_signature_method";
private static final String OAUTH_SIGNATURE_METHOD_VALUE = "HMAC-SHA1";
private static final String OAUTH_TIMESTAMP = "oauth_timestamp";

private static final String OAUTH_VERSION = "oauth_version";
private static final String OAUTH_VERSION_VALUE = "1.0";

private final String consumerKey;
private final String consumerSecret;

private final Random random;
private BasicAuthInterceptor(String consumerKey, String consumerSecret, Random random) {
    this.consumerKey = consumerKey;
    this.consumerSecret = consumerSecret;

    this.random = random;
}
@Override
public Response intercept(Chain chain) throws IOException {
    return chain.proceed(signRequest(chain.request()));
}

public Request signRequest(Request request) throws IOException {
    byte[] nonce = new byte[32];
    random.nextBytes(nonce);
    String oauthNonce = ByteString.of(nonce).base64().replaceAll("\\W", "");
    String oauthTimestamp = String.valueOf(System.currentTimeMillis());

    String consumerKeyValue = ESCAPER.escape(consumerKey);


    SortedMap<String, String> parameters = new TreeMap<>();
    parameters.put(OAUTH_CONSUMER_KEY, consumerKeyValue);

    parameters.put(OAUTH_NONCE, oauthNonce);
    parameters.put(OAUTH_TIMESTAMP, oauthTimestamp);
    parameters.put(OAUTH_SIGNATURE_METHOD, OAUTH_SIGNATURE_METHOD_VALUE);
    parameters.put(OAUTH_VERSION, OAUTH_VERSION_VALUE);

    HttpUrl url = request.url();
    for (int i = 0; i < url.querySize(); i++) {
        parameters.put(ESCAPER.escape(url.queryParameterName(i)),
                ESCAPER.escape(url.queryParameterValue(i)));
    }


    RequestBody requestBody = request.body();
    Buffer body = new Buffer();

    if (requestBody != null) {
        requestBody.writeTo(body);
    }

    while (!body.exhausted()) {
        long keyEnd = body.indexOf((byte) '=');
        if (keyEnd == -1) throw new IllegalStateException("Key with no value: " + body.readUtf8());
        String key = body.readUtf8(keyEnd);
        body.skip(1); // Equals.

        long valueEnd = body.indexOf((byte) '&');
        String value = valueEnd == -1 ? body.readUtf8() : body.readUtf8(valueEnd);
        if (valueEnd != -1) body.skip(1); // Ampersand.

        parameters.put(key, value);
    }

    Buffer base = new Buffer();
    String method = request.method();
    base.writeUtf8(method);
    base.writeByte('&');
    base.writeUtf8(ESCAPER.escape(request.url().newBuilder().query(null).build().toString()));
    base.writeByte('&');

    boolean first = true;
    for (Map.Entry<String, String> entry : parameters.entrySet()) {
        if (!first) base.writeUtf8(ESCAPER.escape("&"));
        first = false;
        base.writeUtf8(ESCAPER.escape(entry.getKey()));
        base.writeUtf8(ESCAPER.escape("="));
        base.writeUtf8(ESCAPER.escape(entry.getValue()));
    }

    String signingKey =
            ESCAPER.escape(consumerSecret);// + "&" + ESCAPER.escape(accessSecret);

    SecretKeySpec keySpec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");
    Mac mac;
    try {
        mac = Mac.getInstance("HmacSHA1");
        mac.init(keySpec);
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        throw new IllegalStateException(e);
    }
    byte[] result = mac.doFinal(base.readByteArray());
    String signature = ByteString.of(result).base64();

    String authorization = "OAuth "
            + OAUTH_CONSUMER_KEY + "=\"" + consumerKeyValue + "\", "
            + OAUTH_NONCE + "=\"" + oauthNonce + "\", "
            + OAUTH_SIGNATURE + "=\"" + ESCAPER.escape(signature) + "\", "
            + OAUTH_SIGNATURE_METHOD + "=\"" + OAUTH_SIGNATURE_METHOD_VALUE + "\", "
            + OAUTH_TIMESTAMP + "=\"" + oauthTimestamp + "\", "

            + OAUTH_VERSION + "=\"" + OAUTH_VERSION_VALUE + "\"";

    Log.d("message","--"+authorization);


    return request.newBuilder()
            .addHeader("Authorization", authorization)
    .addHeader("Content-Type", "application/json;charset=UTF-8")
    .addHeader("Accept", "application/json;versions=1")
            .build();
}

public static final class Builder {
    private String consumerKey;
    private String consumerSecret;

    private Random random = new SecureRandom();


    public Builder consumerKey(String consumerKey) {
        if (consumerKey == null) throw new NullPointerException("consumerKey = null");
        this.consumerKey = consumerKey;
        return this;
    }

    public Builder consumerSecret(String consumerSecret) {
        if (consumerSecret == null) throw new NullPointerException("consumerSecret = null");
        this.consumerSecret = consumerSecret;
        return this;
    }



    public Builder random(Random random) {
        if (random == null) throw new NullPointerException("random == null");
        this.random = random;
        return this;
    }



    public BasicAuthInterceptor build() {
        if (consumerKey == null) throw new IllegalStateException("consumerKey not set");
        if (consumerSecret == null) throw new IllegalStateException("consumerSecret not set");

    }
}
}

远程 API 调用

public final class RemoteApiCalls {
private static final String TAG = "RemoteApiCalls";

public static final class Builder {
    RemoteRetrofitInterfaces mService;
    Retrofit mRetrofit;

    public Builder remoteApiCall(String url,Context mContext) {
        return remoteApiCall(mContext,url, 40, 40, 40);
    }

    BasicAuthInterceptor oauth1 = new BasicAuthInterceptor.Builder()
            .consumerKey("keyhere")//i have added keys
            .consumerSecret("secert here")//i have added secertkeys
            .build();

    public Builder remoteApiCall(Context mContext, String url, int connectionTimeout, int readTimeout, int writeTimeout) {

         HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS).addInterceptor(interceptor).addInterceptor(oauth1)
                .build();

        mRetrofit = new Retrofit.Builder()
                .baseUrl(url).addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();
        mService = mRetrofit.create(RemoteRetrofitInterfaces.class);


        return this;
    }



    public void getProductCatogry()

    {

        Call<ProductCategoryResponse> mApiCall = mService.getListCategory();
        mApiCall.enqueue(new Callback<ProductCategoryResponse>() {
            @Override
            public void onResponse(Call<ProductCategoryResponse> call, Response<ProductCategoryResponse> response) {

                if (response.isSuccessful()) {


                } else {

                }
            }

            @Override
            public void onFailure(Call<ProductCategoryResponse> call, Throwable t) {
t.printStackTrace();
            }


        });

    }

}

}

RemoteRetrofitInterfaces.java

public interface RemoteRetrofitInterfaces {

@GET("products")
Call<ProductCategoryResponse> getListCategory();
}

在我调用的主要活动中

 new RemoteApiCalls.Builder().remoteApiCall("http://mywebsite.com/wp-json/wc/v1/",getApplicationContext()).getProductCatogry();

仍然收到 401 错误

{"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}

Woo Commerce 使用的版本是 2.6.4 版 APi 版本为 v1

谁能帮我解决这个问题,我想通过改造本身来实现。

【问题讨论】:

  • 我们不需要传递所有项目,改造自己处理所有。请在 StackOverflow 中查看我的回答 link。对我的回答有任何疑问。
  • @SubinBabu 可能是,但是您检查了大约 1.6 年前提出的这个问题,而您提到的问题仅在一个月前提出,所以这不是您所说的问题的重复,您可以提及类似的问题问题。

标签: android api oauth retrofit2 woocommerce-rest-api


【解决方案1】:

我终于找到了解决方案,希望这对其他人有所帮助

我浏览了各种文件

1)Using the WooCommerce REST API – Introduction

2)woocommerce-rest-api-docs

3)Scribe

4)scribe:1.3.5

在参考了上述文档和源代码后,我最终创建了一个库,为 woocommerce HTTP android 执行 OAuth 1.0a “单腿”身份验证

完整的描述已添加到我的图书馆的自述部分

在这里查看图书馆

WoocommerceAndroidOAuth1 LIBRARY

【讨论】:

    猜你喜欢
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2018-05-26
    • 2018-05-31
    • 2014-05-19
    • 1970-01-01
    相关资源
    最近更新 更多