我正在编写一个基于节点的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)结果不确定(解压缩工具无法解压缩自己的压缩......)
感谢您提供可能有用的建议,提示或工具
答案 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'));
}