使用nodejs和soap

时间:2016-09-26 18:19:43

标签: javascript node.js web-services soap

我使用了使用PasswordDigest身份验证的SOAP。 我使用了这个库:https://github.com/vpulim/node-soap

我使用nodejs版本v0.10.29在Debian上运行此代码并且它正常工作。

现在我需要让它在运行nodejs v6.6.0的Windows计算机上运行,​​而且它不再工作了。

我有以下消息:

  

无法对安全令牌进行身份验证或授权

我怀疑加密lib有问题,这段代码可能是:

"use strict";
var crypto = require('crypto');
exports.passwordDigest = function passwordDigest(nonce, created, password) {
  // digest = base64 ( sha1 ( nonce + created + password ) )
  var pwHash = crypto.createHash('sha1');
  var rawNonce = new Buffer(nonce || '', 'base64').toString('binary');
  pwHash.update(rawNonce + created + password);
  return pwHash.digest('base64');
};

来自https://github.com/vpulim/node-soap/blob/master/lib/utils.js

2 个答案:

答案 0 :(得分:1)

好的,所以这就是我解决它的方式:

SOAP库具有构建WSSE安全头的功能,该头位于soap / lib / security / templates / WSSecurity.js中。

问题是它放在标题中的UsernameToken与soapUI正在使用的实际结果(在我的示例中)不一致。

原始代码:

 "<wsse:UsernameToken xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"SecurityToken-" + created + "\">

虽然我需要的是:

<wsse:UsernameToken wsu:Id="UsernameToken-<token>">

为了获得正确的令牌,我使用了来自npm(https://www.npmjs.com/package/wsse)的WSSE库。

我所要做的就是包括包,在自述文件中定义令牌:

const wsse = require('wsse');
const token = wsse({ username: '<username>', password: '<password>' })

然后为标题中的EncodingType属性调用token.getNonce()以获取正确的标记和token.getPasswordDigest()。

之后一切都按预期工作。

希望有所帮助!

答案 1 :(得分:-2)

我使用@MTM回答推送模块。 请看看

https://www.npmjs.com/package/wssecurity-soap

修复它的代码,以防任何人想要审查(与soap wssecurity auth实现包括修复相同)

var crypto = require('crypto');
var wsse = require('wsse');

var validPasswordTypes = ['PasswordDigest', 'PasswordText'];

function WSSecurity(username, password, options) {
  options = options || {};
  this._username = username;
  this._password = password;    
  if (typeof options === 'string') {
    this._passwordType = options ? 
     options : 
     'PasswordText';
    options = {};
  } else {
    this._passwordType = options.passwordType ? 
     options.passwordType : 
     'PasswordText';
  }

  if (validPasswordTypes.indexOf(this._passwordType) === -1) {
    this._passwordType = 'PasswordText';
  }

  this._hasTimeStamp = options.hasTimeStamp || typeof options.hasTimeStamp === 'boolean' ? !!options.hasTimeStamp : true;
  if (options.hasNonce != null) {
    this._hasNonce = !!options.hasNonce;
  }
  this._hasTokenCreated = options.hasTokenCreated || typeof options.hasTokenCreated === 'boolean' ? !!options.hasTokenCreated : true;
  if (options.actor != null) {
    this._actor = options.actor;
  }
  if (options.mustUnderstand != null) {
    this._mustUnderstand = !!options.mustUnderstand;
  }
}

WSSecurity.prototype.toXML = function() {
  this._token = wsse({ 
    username: this._username, 
    password: this._password 
  })
  function getDate(d) {
    function pad(n) {
      return n < 10 ? '0' + n : n;
    }
    return d.getUTCFullYear() + '-'
      + pad(d.getUTCMonth() + 1) + '-'
      + pad(d.getUTCDate()) + 'T'
      + pad(d.getUTCHours()) + ':'
      + pad(d.getUTCMinutes()) + ':'
      + pad(d.getUTCSeconds()) + 'Z';
  }
  var now = new Date(this._token.getCreated());
  var created = this._token.getCreated() ; 
  var timeStampXml = '';
  if (this._hasTimeStamp) {
    var expires = getDate( new Date(now.getTime() + (1000 * 600)) );
    timeStampXml = "<wsu:Timestamp wsu:Id=\"Timestamp-"+created+"\">" +
      "<wsu:Created>"+created+"</wsu:Created>" +
      "<wsu:Expires>"+expires+"</wsu:Expires>" +
      "</wsu:Timestamp>";
  }

  var password, nonce;
  if (this._hasNonce || this._passwordType !== 'PasswordText') {
    var nHash = crypto.createHash('sha1');
    nHash.update(created + Math.random());
    nonce = nHash.digest('base64');
  }
  if (this._passwordType === 'PasswordText') {
    password = "<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" + this._password + "</wsse:Password>";
    if (nonce) {
      password += "<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + nonce + "</wsse:Nonce>";
    }
  } else {
    password = "<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + this._token.getPasswordDigest() + "</wsse:Password>" +
      "<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + this._token.getNonceBase64() + "</wsse:Nonce>";
  }

  return "<wsse:Security " + (this._actor ? "soap:actor=\"" + this._actor + "\" " : "") +
    (this._mustUnderstand ? "soap:mustUnderstand=\"1\" " : "") +
    "xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" +
    timeStampXml +
    "<wsse:UsernameToken wsu:Id=\"UsernameToken-" + created +"\">"+
    "<wsse:Username>" + this._username + "</wsse:Username>" +
    password +
    (this._hasTokenCreated ? "<wsu:Created>" + created + "</wsu:Created>" : "") +
    "</wsse:UsernameToken>" +
    "</wsse:Security>";
};

module.exports = WSSecurity;