【问题标题】:Dart OAuth 1.0 - Invalid signature - provided signature does not matchDart OAuth 1.0 - 无效签名 - 提供的签名不匹配
【发布时间】:2020-10-23 19:43:00
【问题描述】:

我正在使用 OAuth 1.0 调用 api,并且我正在使用以下包进行 api 调用。但我收到以下错误。请任何人指导我修复此错误。

api调用库:

https://github.com/nbspou/dart-oauth1

我的代码:

const String apiKey = 'ck_789b63aee985c4569bfa5ae4724861ae5c74c337';
  const String apiSecret = 'cs_0f0addbc9c16042d5689a4cfe6fbfd209b00d55b';
  var clientCredentials = new oauth1.ClientCredentials(Uri.encodeComponent(apiKey), Uri.encodeComponent(apiSecret));

  // create Authorization object with client credentials and platform definition
  //var auth = new oauth1.Authorization(clientCredentials, platform);
  var auth = new oauth1.Credentials(apiKey, apiSecret);
  // yeah, you got token credentials
  // create Client object
  var client = new oauth1.Client(platform.signatureMethod, clientCredentials, auth);

  // now you can access to protected resources via client
  client.get('http://demo2.signitydemo.in/foodemporium/wp-json/wc/v3/products/categories').then((res) {
    print("res.body===${res.body}");
    print("statusCode===${res.statusCode}");
    print("headers===${res.headers}");

  });




{"code":"woocommerce_rest_authentication_error","message":"Invalid signature - provided signature does not match.","data":{"status":401}}

标题:

{link: <http://demo2.signitydemo.in/foodemporium/wp-json/>; rel="https://api.w.org/", access-control-allow-headers: Authorization, Content-Type, connection: keep-alive, date: Fri, 03 Jul 2020 05:32:04 GMT, transfer-encoding: chunked, vary: Origin, access-control-expose-headers: X-WP-Total, X-WP-TotalPages, x-robots-tag: noindex, content-type: application/json; charset=UTF-8, x-content-type-options: nosniff, server: nginx}

我已经在 Postman 中测试过 API。它工作正常,我得到了回应。请参阅下面的邮递员 API 请求。

【问题讨论】:

    标签: android http flutter dart oauth-1.0a


    【解决方案1】:

    所以我放弃了 Woocommerce 包来创建一个函数,该函数使用 oauth 1.0 身份验证的新参数解析 url

    import 'dart:collection';
    import 'dart:math';
    import 'package:crypto/crypto.dart' as crypto;
    import 'package:http/http.dart' as http;
    import 'dart:convert';
    
    /// This Generates a valid OAuth 1.0 URL
    ///
    /// if [isHttps] is true we just return the URL with
    /// [consumerKey] and [consumerSecret] as query parameters
    String _getOAuthURL(String requestMethod, String queryUrl) {
          String consumerKey = cKey;
          String consumerSecret = cSecret;
    
        String token = "";
        String url = queryUrl;
        bool containsQueryParams = url.contains("?");
    
        Random rand = Random();
        List<int> codeUnits = List.generate(10, (index) {
          return rand.nextInt(26) + 97;
        });
    
        /// Random string uniquely generated to identify each signed request
        String nonce = String.fromCharCodes(codeUnits);
    
        /// The timestamp allows the Service Provider to only keep nonce values for a limited time
        int timestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000;
    
        String parameters = "oauth_consumer_key=" +
            consumerKey +
            "&oauth_nonce=" +
            nonce +
            "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" +
            timestamp.toString() +
            "&oauth_token=" +
            token +
            "&oauth_version=1.0&";
    
        if (containsQueryParams == true) {
          parameters = parameters + url.split("?")[1];
        } else {
          parameters = parameters.substring(0, parameters.length - 1);
        }
    
        Map<dynamic, dynamic> params = QueryString.parse(parameters);
        Map<dynamic, dynamic> treeMap = new SplayTreeMap<dynamic, dynamic>();
        treeMap.addAll(params);
    
        String parameterString = "";
    
        for (var key in treeMap.keys) {
          parameterString = parameterString +
              Uri.encodeQueryComponent(key) +
              "=" +
              treeMap[key] +
              "&";
        }
    
        parameterString = parameterString.substring(0, parameterString.length - 1);
    
        String method = requestMethod;
        String baseString = method +
            "&" +
            Uri.encodeQueryComponent(
                containsQueryParams == true ? url.split("?")[0] : url) +
            "&" +
            Uri.encodeQueryComponent(parameterString);
    
        String signingKey = consumerSecret + "&" + token;
        crypto.Hmac hmacSha1 =
            crypto.Hmac(crypto.sha1, utf8.encode(signingKey)); // HMAC-SHA1
    
        /// The Signature is used by the server to verify the
        /// authenticity of the request and prevent unauthorized access.
        /// Here we use HMAC-SHA1 method.
        crypto.Digest signature = hmacSha1.convert(utf8.encode(baseString));
    
        String finalSignature = base64Encode(signature.bytes);
    
        String requestUrl = "";
    
        if (containsQueryParams == true) {
          requestUrl = url.split("?")[0] +
              "?" +
              parameterString +
              "&oauth_signature=" +
              Uri.encodeQueryComponent(finalSignature);
        } else {
          requestUrl = url +
              "?" +
              parameterString +
              "&oauth_signature=" +
              Uri.encodeQueryComponent(finalSignature);
        }
    
        return requestUrl;
      }
    
    

    使用上面的这个函数,我可以在异步函数中发出请求,如下所示:

    Future fetchWooProducts() async {
        http.Response response = await http.get(_getOAuthURL("GET", '$productsUrl'),
             headers: {"Content-Type": "Application/json"});//using JWT token for WP authentication is not needed
        print(response.body);
    }
    
    

    【讨论】:

    • 非常感谢,成功了!
    【解决方案2】:

    和 QueryString 类是一样的

    class QueryString {
    /// Parses the given query string into a Map.
    static Map parse(String query) {
    var search = new RegExp('([^&=]+)=?([^&]*)');
    var result = new Map();
    
    // Get rid off the beginning ? in query strings.
    if (query.startsWith('?')) query = query.substring(1);
    
    // A custom decoder.
    decode(String s) => Uri.decodeComponent(s.replaceAll('+', ' '));
    
    // Go through all the matches and build the result map.
    for (Match match in search.allMatches(query)) {
      result[decode(match.group(1))] = decode(match.group(2));
    }
    
    return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多