【问题标题】:WooCommerce Api authentication error using java使用 java 的 WooCommerce Api 身份验证错误
【发布时间】:2015-06-02 07:57:27
【问题描述】:

​我在连接 WooCommerce API (http://woothemes.github.io/woocommerce-rest-api-docs/#authentication) 时遇到问题。我成功地能够使用java程序生成签名,并且还检查了在控制台中链接的具有相同时间戳和随机数的生成签名(如WooCommerce文档中给出的)是否存在任何差异,但生成的签名在链接和java输出上是相同的安慰。

我们的工作过程如下:

​1.我们使用 java 程序在签名基本字符串和密钥的帮助下生成了签名。签名基本字符串如下所示:

GET&http%3A%2F%2FEndPointURL%2Fwc-api%2Fv2%2Forders&oauth_consumer_key%3D%26oauth_nonce%3D70810941%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1433226349%26oauth_version%3D1.0

2。​当我们尝试访问 url http://EndPointURL/wc-api/v2/orders 时,它显示以下错误:

{"errors":[{"code":"woocommerce_api_authentication_error","message":"Invalid Signature - provided signature does not match"}]}

3.我们还借助 Linked in test Console 生成了签名,使用相同的时间戳和 nonce 值并获得相同的签名。但我们无法访问数据。

我使用的java代码如下:

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;


public class OAuthForWooCommerce {

private static String key = "consumer_Key";
private static String secret = "consumer_Secret";

private static final String HMAC_SHA1 = "HmacSHA1";

private static final String ENC = "UTF-8";

private static Base64 base64 = new Base64();


private static String getSignature(String url, String params)
        throws UnsupportedEncodingException, NoSuchAlgorithmException,
        InvalidKeyException {
    /**
     * base has three parts, they are connected by "&": 1) protocol 2) URL
     * (need to be URLEncoded) 3) Parameter List (need to be URLEncoded).
     */
    StringBuilder base = new StringBuilder();
    base.append("GET&");
    base.append(url);
    base.append("&");
    base.append(params);
    System.out.println("String for oauth_signature generation:" + base);
    // yea, don't ask me why, it is needed to append a "&" to the end of
    // secret key.
    byte[] keyBytes = (secret + "&").getBytes(ENC);

    SecretKey key = new SecretKeySpec(keyBytes, HMAC_SHA1);

    Mac mac = Mac.getInstance(HMAC_SHA1);
    mac.init(key);

    // encode it, base64 it, change it to string and return.
    return new String(base64.encode(mac.doFinal(base.toString().getBytes(
            ENC))), ENC).trim();
}


public static void main(String[] args) throws ClientProtocolException,
        IOException, URISyntaxException, InvalidKeyException,
        NoSuchAlgorithmException {
     System.out.println("*** Welcome to WooCommerce Klipfolio integration Wizard ***");
    HttpClient httpclient = new DefaultHttpClient();
    List<NameValuePair> qparams = new ArrayList<NameValuePair>();
    // These params should ordered in key
    //qparams.add(new BasicNameValuePair("oauth_callback", "oob"));
    qparams.add(new BasicNameValuePair("oauth_consumer_key", key));
    String nonce = RandomStringUtils.randomAlphanumeric(32);
    //String nonce2 = URLEncoder.encode(nonce1, "UTF-8");
    qparams.add(new BasicNameValuePair("oauth_nonce", nonce));
    //qparams.add(new BasicNameValuePair("oauth_nonce", ""+ (int) (Math.random() * 100000000)));
    qparams.add(new BasicNameValuePair("oauth_signature_method",
            "HMAC-SHA1"));
    qparams.add(new BasicNameValuePair("oauth_timestamp", ""
            + (System.currentTimeMillis() / 1000)));
    qparams.add(new BasicNameValuePair("oauth_version", "1.0"));

    // generate the oauth_signature
    String signature = getSignature(URLEncoder.encode(
            "http://MY_END_URL/wc-api/v2/orders", ENC),
            URLEncoder.encode(URLEncodedUtils.format(qparams, ENC), ENC));
    System.out.println("Getting Oauth Signature...");
    // add it to params list
    qparams.add(new BasicNameValuePair("oauth_signature", signature));

    // generate URI which lead to access_token and token_secret.
    URI uri = URIUtils.createURI("http", "MY_END _URL", -1,
            "wc-api/v2/orders",
            URLEncodedUtils.format(qparams, ENC), null);

    System.out.println("Connecting to  the URL : \n"
            + uri.toString());

    HttpGet httpget = new HttpGet(uri);
    // output the response content.
    System.out.println("Getting Response from the server :");

    HttpResponse response = httpclient.execute(httpget);
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        InputStream instream = entity.getContent();
        int len;
        byte[] tmp = new byte[2048];
        while ((len = instream.read(tmp)) != -1) {
            System.out.println(new String(tmp, 0, len, ENC));
        }
    }
}

}

请告诉我哪里做错了。

谢谢,

【问题讨论】:

  • 你找到答案了吗?
  • 不,这仍然是未决案件!!
  • 我用 JS 解决了这个问题。问题在于您的编码部分,您可以尝试在创建密钥时删除 +&
  • 你在 Github 上看过那段代码吗?
  • 你试过 wc-api (github.com/icoderman/wc-api-java) 吗?

标签: java wordpress api woocommerce woothemes


【解决方案1】:

根据文档,您必须从参数中删除版本号。我认为您还应该删除在生成签名时添加到密钥中的“&”,因为没有它我设法得到 200 个响应。

需要的参数是:oauth_consumer_key、oauth_timestamp、oauth_nonce、oauth_signature 和 oauth_signature_method。 oauth_version 不是必需的,必须省略。

在将参数添加到用于创建签名的字符串之前,您还应该按字节顺序对参数进行排序。

另外,我建议您通过更改the message line 进行调试,以查看您发送到服务器的签名以及您应该发送的签名。

例如,您可以将其更改为:

throw new Exception( __( 'Invalid Signature - provided signature does not match Secret:' . $user->woocommerce_api_consumer_secret . ', StringToSign: ' . $string_to_sign . ', TakenSign: ' . $consumer_signature . ', GeneratedSign: ' . $signature, 'woocommerce' ), 401 );

【讨论】:

    【解决方案2】:

    感谢您的代码 Archit,这帮助我跳过了障碍。

    我已经更新了你的代码,下面的工作正常。

    package com.woocommerce.experiments;
    
    import org.apache.commons.codec.EncoderException;
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.codec.net.URLCodec;
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang3.RandomStringUtils;
    import org.apache.http.Consts;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.utils.URIUtils;
    import org.apache.http.client.utils.URLEncodedUtils;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.message.BasicNameValuePair;
    
    import javax.crypto.Mac;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.net.URLEncoder;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.TreeMap;
    
    public class OAuthForWooCommerce {
    
      private static String key = "ck_your_consumer_key";
      private static String secret = "cs_your_consumer_secret";
    
      private static final String HMAC_SHA1 = "HmacSHA1";
    
      private static final String ENC = "UTF-8";
    
      private static Base64 base64 = new Base64();
    
      private static String getSignature(String url, String params)
              throws UnsupportedEncodingException, NoSuchAlgorithmException,
              InvalidKeyException, EncoderException {
        /**
         * base has three parts, they are connected by "&": 1) protocol 2) URL
         * (need to be URLEncoded) 3) Parameter List (need to be URLEncoded).
         */
        StringBuilder base = new StringBuilder();
        base.append("GET&");
    
       //follow Step 2 and encode
        base.append(new URLCodec(Consts.UTF_8.displayName()).encode(url));
        base.append("&");
        base.append(params);
    
        System.out.println("String for oauth_signature generation: " + base);
    
        byte[] keyBytes = (String.format("%s", secret)).getBytes(ENC);
    
        SecretKey key = new SecretKeySpec(keyBytes, HMAC_SHA1);
    
        Mac mac = Mac.getInstance(HMAC_SHA1);
        mac.init(key);
    
        // encode it, base64 it, change it to string and return.
        String signature = new String(base64.encode(mac.doFinal(base.toString().getBytes(ENC))), ENC).trim();
        return signature;
      }
    
    
      public static void main(String[] args) throws IOException, URISyntaxException, InvalidKeyException,
              NoSuchAlgorithmException, EncoderException {
    
        String nonce = RandomStringUtils.randomAlphanumeric(32);
    
        Map<String, String> paramMap = new TreeMap<>();
        paramMap.put("oauth_consumer_key", key);
        paramMap.put("oauth_timestamp", "" + (System.currentTimeMillis() / 1000));
        paramMap.put("oauth_nonce", nonce);
        paramMap.put("oauth_signature_method", "HMAC-SHA1");
    
        List<NameValuePair> qparams = new ArrayList<>();
    
        //uksort( $params, 'strcmp' ) mimic
        paramMap.entrySet().stream().forEach(stringStringEntry -> qparams.add(new BasicNameValuePair(stringStringEntry.getKey(), stringStringEntry.getValue())));
    
        //double encode Step 3 (in order to replace '%' with '%25') after sorting (Step 4)
        String encodedParams = URLEncoder.encode(URLEncodedUtils.format(qparams, ENC), ENC);
    
        System.out.println("Encoded Params "+ encodedParams);
    
        String signature = getSignature("http://your_end_url/wc-api/v2/orders", encodedParams);
    
        qparams.add(new BasicNameValuePair("oauth_signature", signature));
    
        HttpClient httpclient = HttpClientBuilder.create().build();
    
        System.out.println("Getting Oauth Signature...");
    
        // generate URI which lead to access_token and token_secret.
        URI uri = URIUtils.createURI("http", "your_end_url", -1, "wc-api/v2/orders", URLEncodedUtils.format(qparams, ENC), null);
    
        System.out.println("Connecting to  the URL : \n" + uri.toString());
    
        HttpGet httpget = new HttpGet(uri);
        httpget.setHeader("X-Stream" , "true");
    
        // output the response content.
        System.out.println("Getting Response from the server :");
    
        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
    
        System.out.println("Response Code " + response.getStatusLine().getStatusCode());
    
        if (entity != null) {
          System.out.println("Json response" + IOUtils.toString(entity.getContent(), ENC));
        }
      }
    }
    

    我希望这对您(希望不会迟到!)和其他人有所帮助。认证的分步流程可以在WooCommerce REST API Documentation找到

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-31
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      • 2019-05-06
      相关资源
      最近更新 更多