使用NodeJS使用压缩的base64查询参数

时间:2014-07-18 16:16:09

标签: node.js zlib

我正在编写一个基于节点的Web服务,期望第三方发送一个放气和base64编码的SAML请求。在一天中的大部分时间里徘徊之后,我担心我不确定我甚至不知道该问什么(如果这是一个骗局我道歉)。

文档说:

  

SAMLRequest首先是DEFLATE压缩,然后是Base 64编码,然后是URL编码。必须对其进行解码和解析

Webstorm控制台日志具有以下查询字符串:

  

GET /登录资讯?SAMLRequest = fZJRa9swEMff9ymE3m1LipM4InbJ0mwrNCM0bqF9Gap8cQW2lOnksH37ObFbWgZ9lLj76X%2F30%2FLqT9uQE3g0zuaUx4wSsNpVxtY5vS%2B%2FRRm9Kr4sUbWNOMpVF17sHfzuAANZIYIPfd%2FaWexa8HvwJ6Ph%2Fu42py8hHFEmCV%2BImM%2BymMWCswRBd96Ev1GrrKrBJ2eueuXokUPJdc83VoVLqDPqA4lPmJwwxpLG1cZScnOd018HJeaLSsNkqhfAqql6nsyyVFQiEweWqnlfhrv%2BKXOCnB5Ug3C%2BwQ5uLAZlQ04F42nE5hHPSj6VKZc8jfmcP1Gy8y447Zqvxg6L6byVTqFBaVULKIOW%2B9X2VoqYyeehCOWPstxFq36yg9LhAjmZCvzPviOn352rGyAbG8AfvUEg%2B3E3ZDvshpKHVy3irKUXZVEOIj5PcBzj0mLwJi9z%2BveEzwFvRmgxLr%2B%2BxI21axN4i5zUqJIyjTaP23SzftyK9Wwm%2FnO8TN6HKMbjx79U%2FAM%3D

的输出
console.log(req.query.SAMLRequest)

显示自动完成URL解码:

  

fZJRa9swEMff9ymE3m1LipM4InbJ0mwrNCM0bqF9Gap8cQW2lOnksH37ObFbWgZ9lLj76X / 30 / LqT9uQE3g0zuaUx4wSsNpVxtY5vS + / RRm9Kr4sUbWNOMpVF17sHfzuAANZIYIPfd / aWexa8HvwJ6Ph / u42py8hHFEmCV + 1mM的+ ymMWCswRBd96Ev1GrrKrBJ2eueuXokUPJdc83VoVLqDPqA4lPmJwwxpLG1cZScnOd018HJeaLSsNkqhfAqql6nsyyVFQiEweWqnlfhrv + KXOCnB5Ug3C + wQ5uLAZlQ04F42nE5hHPSj6VKZc8jfmcP1Gy8y447Zqvxg6L6byVTqFBaVULKIOW + 9X2VoqYyeehCOWPstxFq36yg9LhAjmZCvzPviOn352rGyAbG8AfvUEg + 3E3ZDvshpKHVy3irKUXZVEOIj5PcBzj0mLwJi9z + veEzwFvRmgxLr ++ xI21axN4i5zUqJIyjTaP23SzftyK9Wwm / nO8TN6HKMbjx79U / AM =

所以我假设我必须解码base64然后INFLATE它。 (我试图膨胀然后解码,但仍然失败,这是最有意义的):

var zlibJS = require('zlibjs');  //I've tried Node's own zlib but that only appears to work with call backs
...
var b = new Buffer(samlReq, 'base64');
var decoded = b.toString();
var inflated = zlibJS.inflateSync(decoded); //https://github.com/imaya/zlib.js/blob/master/test/node-test.js
//I get an Unsupported compression method 
...//relooking at the test it appears it wants a buffer so switch the above line for this
var inflated = zlibJS.inflateSync(b); // same 500 error

通过github源查看当查找压缩方法时切换到默认值时会抛出此错误,但是,我看不到我希望设置的位置。 我试图像疯了一样记录(为了便于阅读而被删除)并将每一步放入base64解码器(http://www.motobit.com/util/base64-decoder-encoder.asp),url解码器(http://meyerweb.com/eric/tools/dencoder/)和字符串解压缩器(http://i-tools.org/gzip)结果不确定(解压缩工具无法解压缩自己的压缩......)

感谢您提供可能有用的建议,提示或工具

3 个答案:

答案 0 :(得分:3)

我看到另一个提及pako的答案,维基百科在ZLib文章中提到它,所以我给了它一个旋转,它第二次尝试:

var pako = require('pako'); 
...
var b = new Buffer(samlReq, 'base64');
var inflated = pako.inflateRaw(b, {to:'string'}); 

答案 1 :(得分:1)

根据您的问题,我推断出您正在尝试制作应该缩小的SAML请求,base64编码以及之后的URL编码(最后一部分仅因为它用作网址的一部分)

我不确定是否可以使用异步来解决您的同步问题,但我会选择与此类似的东西:

var async = require('async');
var zlib = require('zlib');
var url = require('url');

var samlRequest = '<?xml version="1.0" encoding="UTF-8"?>'
  + '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">'
  + '...'
  + '</samlp:AuthnRequest>';

var buffer = new Buffer(samlRequest);

async.waterfall(
  [
    function deflate(callback) {
      zlib.deflate(buffer, function deflated(err, resultBuffer) {
        if (err) {
          callback(err);
          return;
        }

        callback(null, resultBuffer);
      });
    },
    function encode(buffer, callback) {
      callback(null, buffer.toString('base64'));
    },
    function urlEncode(request, callback) {
      callback(null, encodeURIComponent(request));
    }
  ], function handleResult(err, urlEncodedRequest) {
    if (err) {
      console.log(err);
      return;
    }

    var baseUrl = 'http:xxx.salesforce.com/idp/endpoint/HttpRedirect?SAMLRequest=';
    console.log(baseUrl + urlEncodedRequest);
  }
);

samlRequest当然只是一个例子。我使用了三个功能,这肯定是矫枉过正,但我​​想在这个过程中向你展示异步,它很好地展示了所有的步骤。

答案 2 :(得分:1)

由于您使用带有Node.js的服务器端JavaScript,因此可以通过使用Node的内置zlib轻松完成SAML请求和响应有效负载的编码和解码而无需外部依赖性和Buffer支持。不需要像pako这样的外部系统(即使它非常酷)。

我已经用我的saml-encode-decoder-js NPM package完成了这项工作。它像这样用于解码:

var saml = require('saml');

saml.decodeSamlRedirect(xml, function(err, xml) {
  if (!err) {
    console.log("Redirect decoded XML", xml);
  }
}

saml.decodeSamlPost(xml, function(err, xml) {
  if (!err) {
    console.log("POST decoded XML", xml);
  }
}

NPM库只是使用内置函数的捷径。例如,这是saml-encoder-decoder-js解码SAML重定向绑定有效负载的方式:

var zlib = require('zlib');

function decodeSamlRedirect(encoded, cb) {
  if (encoded == null || encoded == "") {
    return cb(new Error('Cannot decode null string'));
  }
  var deflated = new Buffer(decodeURIComponent(encoded), 'base64');

  zlib.inflateRaw(deflated, function (err, inflated) {
    if (!err) {
      return cb(null, inflated.toString('ascii'));
    } else {
      return cb(err);
    }
  });
}

技巧是使用zlib.deflateRaw()zlib.inflateRaw()进行编码和解码。您无法使用deflate()unzip()

如果您正在使用SAML POST绑定,那么实际上这只是使用Node Buffer进行Base64编码/解码的包装器,如下所示:

function decodeSamlPost(encoded, cb) {
  if (encoded == null || encoded == "") {
    return cb(new Error('Cannot decode null string'));
  }
  return cb(null, new Buffer(encoded, 'base64').toString('ascii'));
}