使用 oauth 1.0a 获取 woocommerce rest api 的无效签名错误 [英] Getting Invalid Signature error with woocommerce rest api using oauth 1.0a

查看:38
本文介绍了使用 oauth 1.0a 获取 woocommerce rest api 的无效签名错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 woocommerce rest api 中收到无效签名错误.我也在使用来自 ddo https://github.com/ddo/oauth-1.0 的 oauth 1.0a 脚本一个.我生成了两次 api 密钥.还删除了 woocommerce rest api 文档中要求的 de oauth 脚本中的版本参数 http://woothemes.github.io/woocommerce-rest-api-docs/

网址

<预> <代码> test.dev/wc-api/v3/orders/line_items?oauth_consumer_key=ck_858f9cf8cda8085d5677b2b1d4c12d10897e9702&oauth_nonce=MyriSapnWSopIusSjjuqJ8PLi6RWr0L9&oauth_signature=VfgINTX1FWYu551%2FxlLfipFnDQ8%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1443481966

错误

{"errors":[{"code":"woocommerce_api_authentication_error","message":"无效签名 - 提供的签名不匹配"}]}

js

var oauth = OAuth({消费者: {公开:'ck_858f9cf8cda8085d5677b2b1d4c12d10897e9702',秘密:'cs_7f429ec99905bb444e290bd4852a0c0da2545b21'},签名方法:'HMAC-SHA1'});var request_data = {网址:'http://test.dev/wc-api/v3/orders/line_items',方法:'获取',}$http({网址:request_data.url,方法:request_data.get,参数:oauth.authorize(request_data)}).then(函数successCallback(响应){控制台日志(响应);}, 函数错误回调(响应){控制台日志(响应);});;

解决方案

通过使用来自 Abdul Ahmad 的服务进行修复:httpService.js

angular.module('httpService', []).factory('httpService', httpService);httpService.$inject = ['$http', '$q'];函数 httpService($http, $q) {变量方法 = {httpGet : 'GET',httpPost : 'POST',httpPut : 'PUT',httpDelete : '删除'};函数 baseGet(url) {返回 $http.get(url).then(功能(结果){返回结果数据;},功能(结果){返回 $q.reject(result);});}函数 httpWithParams(url, method, params, data) {返回 $http({网址:网址,方法:方法,参数:参数,数据:数据,数据类型:json",标题:{内容类型":应用程序/json"}}).然后(功能(结果){返回结果数据;},功能(结果){返回 $q.reject(result);});}函数句柄错误(错误){控制台日志(错误);}返回 {baseGet: baseGet,httpWithParams: httpWithParams,句柄错误:句柄错误,方法:方法}}

然后用这个:

var oauth = OAuth({消费者: {公众:'ck_000',秘密:'cs_000'},签名方法:'HMAC-SHA1'});函数 getMyData() {var request_data = {url: 'http://test.dev/wc-api/v3/products',方法:'获取',}return returnData = httpService.httpWithParams(request_data.url, request_data.method, oauth.authorize(request_data)).then(函数(数据){返回数据;},功能(数据){httpService.handleError(data);返回数据;});}

在 oauth 文件中做了一些修改:

if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') {module.exports = OAuth;var CryptoJS = require("crypto-js");}/*** 构造函数* @param {Object} 选择消费者密钥和秘密*/函数 OAuth(opts) {if(!(this instanceof OAuth)) {返回新的 OAuth(opts);}如果(!选择){选择 = {};}如果(!opts.consumer){throw new Error('需要消费者选项');}this.consumer = opts.consumer;this.signature_method = opts.signature_method ||'HMAC-SHA1';this.nonce_length = opts.nonce_length ||32;//this.version = opts.version ||'1.0';this.parameter_seperator = opts.parameter_seperator ||', ';if(typeof opts.last_ampersand === 'undefined') {this.last_ampersand = true;} 别的 {this.last_ampersand = opts.last_ampersand;}开关(this.signature_method){案例'HMAC-SHA1':this.hash = 函数(base_string,key){返回 CryptoJS.HmacSHA1(base_string, key).toString(CryptoJS.enc.Base64);};休息;案例HMAC-SHA256":this.hash = 函数(base_string,key){返回 CryptoJS.HmacSHA256(base_string, key).toString(CryptoJS.enc.Base64);};休息;案例明文":this.hash = 函数(base_string,key){返回键;};休息;案例'RSA-SHA1':throw new Error('oauth-1.0a 目前不支持此签名方法.即将推出...');默认:throw new Error('OAuth 1.0a 协议定义了三种签名方法:HMAC-SHA1、RSA-SHA1 和 PLAINTEXT only');}}/*** OAuth 请求授权* @param {Object} 请求数据* {*     方法,* 网址,*     数据* }* @param {Object} 公共和秘密令牌* @return {Object} OAuth 授权数据*/OAuth.prototype.authorize = 函数(请求,令牌){var oauth_data = {oauth_consumer_key: this.consumer.public,oauth_timestamp: this.getTimeStamp(),oauth_nonce: this.getNonce(),oauth_signature_method: this.signature_method//oauth_version: this.version};如果(!令牌){令牌 = {};}如果(令牌.公共){oauth_data.oauth_token = token.public;}如果(!请求.数据){request.data = {};}oauth_data.oauth_signature = this.getSignature(request, token.secret, oauth_data);返回 oauth_data;};/*** 创建 OAuth 签名* @param {Object} 请求数据* @param {Object} token_secret 公共和秘密令牌* @param {Object} oauth_data OAuth 数据* @return {String} 签名*/OAuth.prototype.getSignature = 函数(请求,token_secret,oauth_data){返回 this.hash(this.getBaseString(request, oauth_data), this.getSigningKey(token_secret));};/*** 基本字符串 = 方法 + 基本 URL + 参数字符串* @param {Object} 请求数据* @param {Object} OAuth 数据* @return {String} 基本字符串*/OAuth.prototype.getBaseString = 函数(请求,oauth_data){返回 request.method.toUpperCase() + '&'+ this.percentEncode(this.getBaseUrl(request.url)) + '&'+ this.percentEncode(this.getParameterString(request, oauth_data));};/*** 从url获取数据* ->与 oauth 数据合并* ->百分比编码密钥 &价值* ->种类** @param {Object} 请求数据* @param {Object} OAuth 数据* @return {Object} 参数字符串数据*/OAuth.prototype.getParameterString = 函数(请求,oauth_data){var base_string_data = this.sortObject(this.percentEncodeData(this.mergeObject(oauth_data, this.mergeObject(request.data, this.deParamUrl(request.url)))));var data_str = '';//base_string_data 到字符串for(base_string_data 中的 var 键){data_str += key + '=' + base_string_data[key] + '&';}//删除最后一个字符data_str = data_str.substr(0, data_str.length - 1);返回数据字符串;};/*** 创建签名密钥* @param {String} token_secret 秘密令牌* @return {String} 签名密钥*/OAuth.prototype.getSigningKey = function(token_secret) {token_secret = token_secret ||'';if(!this.last_ampersand && !token_secret) {返回 this.percentEncode(this.consumer.secret);}返回 this.percentEncode(this.consumer.secret) + '&'+ this.percentEncode(token_secret);};/*** 获取基本网址* @param {String} 网址* @return {字符串}*/OAuth.prototype.getBaseUrl = 函数(网址){返回 url.split('?')[0];};/*** 从字符串中获取数据* @param {String} 字符串* @return {对象}*/OAuth.prototype.deParam = 函数(字符串){var arr = string.split('&');变量数据 = {};for(var i = 0; i < arr.length; i++) {var item = arr[i].split('=');数据[项目[0]] = decodeURIComponent(项目[1]);}返回数据;};/*** 从url获取数据* @param {String} 网址* @return {对象}*/OAuth.prototype.deParamUrl = 函数(网址){var tmp = url.split('?');如果(tmp.length === 1)返回 {};返回 this.deParam(tmp[1]);};/*** 百分比编码* @param {String} str* @return {String} 百分比编码字符串*/OAuth.prototype.percentEncode = function(str) {返回 encodeURIComponent(str).replace(/\!/g, "%21").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");};/*** 百分比编码对象* @param {Object} 数据* @return {Object} 编码数据的百分比*/OAuth.prototype.percentEncodeData = 函数(数据){变量结果 = {};for(数据中的var键){结果[this.percentEncode(key)] = this.percentEncode(data[key]);}返回结果;};/*** 获取 OAuth 数据作为 Header* @param {Object} oauth_data* @return {String} 头部数据键值*/OAuth.prototype.toHeader = 函数(oauth_data){oauth_data = this.sortObject(oauth_data);var header_value = 'OAuth';for(oauth_data 中的 var 键){if (key.indexOf('oauth_') === -1)继续;header_value += this.percentEncode(key) + '="' + this.percentEncode(oauth_data[key]) + '"' + this.parameter_seperator;}返回 {授权:header_value.substr(0, header_value.length - this.parameter_seperator.length)//截取最后一个字符};};/*** 创建一个输入长度的随机单词字符串* @return {String} 一个随机单词字符串*/OAuth.prototype.getNonce = function() {var word_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';var 结果 = '';for(var i = 0; i < this.nonce_length; i++) {结果 += word_characters[parseInt(Math.random() * word_characters.length, 10)];}返回结果;};/*** 获取当前 Unix 时间戳* @return {Int} 当前的 unix 时间戳*/OAuth.prototype.getTimeStamp = function() {返回 parseInt(new Date().getTime()/1000, 10);};/////////////////////辅助功能/////////////////////*** 合并对象* @param {对象} obj1* @param {对象} obj2* @return {对象}*/OAuth.prototype.mergeObject = function(obj1, obj2) {无功合并_obj = obj1;for(obj2 中的 var 键){合并的对象 [键] = 对象 2[键];}返回merged_obj;};/*** 按键排序对象* @param {Object} 数据* @return {Object} 排序的对象*/OAuth.prototype.sortObject = 函数(数据){var 键 = Object.keys(data);变量结果 = {};键.排序();for(var i = 0; i 

I am getting an invalid signature error in woocommerce rest api. I am also using the oauth 1.0a script from ddo https://github.com/ddo/oauth-1.0a. I generated the api keys twice. Also removed the version parameter inside de oauth script like requested on the woocommerce rest api documentation http://woothemes.github.io/woocommerce-rest-api-docs/

url

test.dev/wc-api/v3/orders/line_items?oauth_consumer_key=ck_858f9cf8cda8085d5677b2b1d4c12d10897e9702&oauth_nonce=MyriSapnWSopIusSjjuqJ8PLi6RWr0L9&oauth_signature=VfgINTX1FWYu551%2FxlLfipFnDQ8%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1443481966

error

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

js

var oauth = OAuth({
    consumer: {
        public: 'ck_858f9cf8cda8085d5677b2b1d4c12d10897e9702',
        secret: 'cs_7f429ec99905bb444e290bd4852a0c0da2545b21 '
    },
    signature_method: 'HMAC-SHA1'
});

var request_data = {
    url: 'http://test.dev/wc-api/v3/orders/line_items',
    method: 'GET',
}

$http({
    url: request_data.url,
    method: request_data.get,
    params: oauth.authorize(request_data)
}).then(function successCallback(response) {
    console.log(response);
}, function errorCallback(response) {
    console.log(response);
});;

解决方案

Fixed it by using a service from Abdul Ahmad: httpService.js

angular.module('httpService', []).factory('httpService', httpService);
httpService.$inject = ['$http', '$q'];

function httpService($http, $q) {

    var methods = {
        httpGet : 'GET',
        httpPost : 'POST',
        httpPut : 'PUT',
        httpDelete : 'DELETE'
    };

    function baseGet(url) {
        return $http.get(url).then(
                function (result) {
                    return result.data;
                },
                function (result) {
                    return $q.reject(result);
                }
            );
    }
    function httpWithParams(url, method, params, data) {
        return $http({
                url: url,
                method: method,
                params: params,
                data: data,
                dataType: "json",
                headers: {
                    "Content-Type": "application/json"
                }
            }).then(
                function (result) {
                    return result.data;
                },
                function (result) {
                    return $q.reject(result);
                }
            );
    }
    function handleError(error) {
            console.log(error);
    }

    return {
        baseGet: baseGet,
        httpWithParams: httpWithParams,
        handleError: handleError,
        methods: methods
    }
}

And then used this:

var oauth = OAuth({
    consumer: {
        public: 'ck_000',
        secret: 'cs_000'
    },
    signature_method: 'HMAC-SHA1'
});

function getMyData() {

    var request_data = {
        url: 'http://test.dev/wc-api/v3/products',
        method: 'get',
    }

    return  returnData = httpService.httpWithParams(request_data.url, request_data.method, oauth.authorize(request_data))
    .then(function(data) {
        return data;
    }, function(data) {
        httpService.handleError(data);
        return data;
    });
}

Made some modification in the oauth file:

if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') {
    module.exports = OAuth;
    var CryptoJS = require("crypto-js");
}

/**
 * Constructor
 * @param {Object} opts consumer key and secret
 */
function OAuth(opts) {
    if(!(this instanceof OAuth)) {
        return new OAuth(opts);
    }

    if(!opts) {
        opts = {};
    }

    if(!opts.consumer) {
        throw new Error('consumer option is required');
    }

    this.consumer            = opts.consumer;
    this.signature_method    = opts.signature_method || 'HMAC-SHA1';
    this.nonce_length        = opts.nonce_length || 32;
    //this.version             = opts.version || '1.0';
    this.parameter_seperator = opts.parameter_seperator || ', ';

    if(typeof opts.last_ampersand === 'undefined') {
        this.last_ampersand = true;
    } else {
        this.last_ampersand = opts.last_ampersand;
    }

    switch (this.signature_method) {
        case 'HMAC-SHA1':
            this.hash = function(base_string, key) {
                return CryptoJS.HmacSHA1(base_string, key).toString(CryptoJS.enc.Base64);
            };
            break;

        case 'HMAC-SHA256':
            this.hash = function(base_string, key) {
                return CryptoJS.HmacSHA256(base_string, key).toString(CryptoJS.enc.Base64);
            };
            break;

        case 'PLAINTEXT':
            this.hash = function(base_string, key) {
                return key;
            };
            break;

        case 'RSA-SHA1':
            throw new Error('oauth-1.0a does not support this signature method right now. Coming Soon...');
        default:
            throw new Error('The OAuth 1.0a protocol defines three signature methods: HMAC-SHA1, RSA-SHA1, and PLAINTEXT only');
    }
}

/**
 * OAuth request authorize
 * @param  {Object} request data
 * {
 *     method,
 *     url,
 *     data
 * }
 * @param  {Object} public and secret token
 * @return {Object} OAuth Authorized data
 */
OAuth.prototype.authorize = function(request, token) {
    var oauth_data = {
        oauth_consumer_key: this.consumer.public,
        oauth_timestamp: this.getTimeStamp(),
        oauth_nonce: this.getNonce(),
        oauth_signature_method: this.signature_method
        //oauth_version: this.version
    };

    if(!token) {
        token = {};
    }

    if(token.public) {
        oauth_data.oauth_token = token.public;
    }

    if(!request.data) {
        request.data = {};
    }

    oauth_data.oauth_signature = this.getSignature(request, token.secret, oauth_data);

    return oauth_data;
};

/**
 * Create a OAuth Signature
 * @param  {Object} request data
 * @param  {Object} token_secret public and secret token
 * @param  {Object} oauth_data   OAuth data
 * @return {String} Signature
 */
OAuth.prototype.getSignature = function(request, token_secret, oauth_data) {
    return this.hash(this.getBaseString(request, oauth_data), this.getSigningKey(token_secret));
};

/**
 * Base String = Method + Base Url + ParameterString
 * @param  {Object} request data
 * @param  {Object} OAuth data
 * @return {String} Base String
 */
OAuth.prototype.getBaseString = function(request, oauth_data) {
    return request.method.toUpperCase() + '&' + this.percentEncode(this.getBaseUrl(request.url)) + '&' + this.percentEncode(this.getParameterString(request, oauth_data));
};

/**
 * Get data from url
 * -> merge with oauth data
 * -> percent encode key & value
 * -> sort
 *
 * @param  {Object} request data
 * @param  {Object} OAuth data
 * @return {Object} Parameter string data
 */
OAuth.prototype.getParameterString = function(request, oauth_data) {
    var base_string_data = this.sortObject(this.percentEncodeData(this.mergeObject(oauth_data, this.mergeObject(request.data, this.deParamUrl(request.url)))));

    var data_str = '';

    //base_string_data to string
    for(var key in base_string_data) {
        data_str += key + '=' + base_string_data[key] + '&';
    }

    //remove the last character
    data_str = data_str.substr(0, data_str.length - 1);
    return data_str;
};

/**
 * Create a Signing Key
 * @param  {String} token_secret Secret Token
 * @return {String} Signing Key
 */
OAuth.prototype.getSigningKey = function(token_secret) {
    token_secret = token_secret || '';

    if(!this.last_ampersand && !token_secret) {
        return this.percentEncode(this.consumer.secret);
    }

    return this.percentEncode(this.consumer.secret) + '&' + this.percentEncode(token_secret);
};

/**
 * Get base url
 * @param  {String} url
 * @return {String}
 */
OAuth.prototype.getBaseUrl = function(url) {
    return url.split('?')[0];
};

/**
 * Get data from String
 * @param  {String} string
 * @return {Object}
 */
OAuth.prototype.deParam = function(string) {
    var arr = string.split('&');
    var data = {};

    for(var i = 0; i < arr.length; i++) {
        var item = arr[i].split('=');
        data[item[0]] = decodeURIComponent(item[1]);
    }
    return data;
};

/**
 * Get data from url
 * @param  {String} url
 * @return {Object}
 */
OAuth.prototype.deParamUrl = function(url) {
    var tmp = url.split('?');

    if (tmp.length === 1)
        return {};

    return this.deParam(tmp[1]);
};

/**
 * Percent Encode
 * @param  {String} str
 * @return {String} percent encoded string
 */
OAuth.prototype.percentEncode = function(str) {
    return encodeURIComponent(str)
        .replace(/\!/g, "%21")
        .replace(/\*/g, "%2A")
        .replace(/\'/g, "%27")
        .replace(/\(/g, "%28")
        .replace(/\)/g, "%29");
};

/**
 * Percent Encode Object
 * @param  {Object} data
 * @return {Object} percent encoded data
 */
OAuth.prototype.percentEncodeData = function(data) {
    var result = {};

    for(var key in data) {
        result[this.percentEncode(key)] = this.percentEncode(data[key]);
    }

    return result;
};

/**
 * Get OAuth data as Header
 * @param  {Object} oauth_data
 * @return {String} Header data key - value
 */
OAuth.prototype.toHeader = function(oauth_data) {
    oauth_data = this.sortObject(oauth_data);

    var header_value = 'OAuth ';

    for(var key in oauth_data) {
        if (key.indexOf('oauth_') === -1)
            continue;
        header_value += this.percentEncode(key) + '="' + this.percentEncode(oauth_data[key]) + '"' + this.parameter_seperator;
    }

    return {
        Authorization: header_value.substr(0, header_value.length - this.parameter_seperator.length) //cut the last chars
    };
};

/**
 * Create a random word characters string with input length
 * @return {String} a random word characters string
 */
OAuth.prototype.getNonce = function() {
    var word_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    var result = '';

    for(var i = 0; i < this.nonce_length; i++) {
        result += word_characters[parseInt(Math.random() * word_characters.length, 10)];
    }

    return result;
};

/**
 * Get Current Unix TimeStamp
 * @return {Int} current unix timestamp
 */
OAuth.prototype.getTimeStamp = function() {
    return parseInt(new Date().getTime()/1000, 10);
};

////////////////////// HELPER FUNCTIONS //////////////////////

/**
 * Merge object
 * @param  {Object} obj1
 * @param  {Object} obj2
 * @return {Object}
 */
OAuth.prototype.mergeObject = function(obj1, obj2) {
    var merged_obj = obj1;
    for(var key in obj2) {
        merged_obj[key] = obj2[key];
    }
    return merged_obj;
};

/**
 * Sort object by key
 * @param  {Object} data
 * @return {Object} sorted object
 */
OAuth.prototype.sortObject = function(data) {
    var keys = Object.keys(data);
    var result = {};

    keys.sort();

    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];
        result[key] = data[key];
    }

    return result;
};

这篇关于使用 oauth 1.0a 获取 woocommerce rest api 的无效签名错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆