如何使用C#正确准备“HTTP重定向绑定”SAML请求
我需要使用HTTP重定向绑定方法创建SP启动的SAML 2.0身份验证事务.原来这很简单.只需获取IdP URI并连接一个查询字符串参数SAMLRequest. param是描述SAML请求的xml的编码块.到现在为止还挺好.
将SAML转换为查询字符串参数时出现问题.我相信这个准备过程应该是: >构建SAML字符串 SAML请求 <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{0}" Version="2.0" AssertionConsumerServiceIndex="0" AttributeConsumingServiceIndex="0"> <saml:Issuer>URN:xx-xx-xx</saml:Issuer> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/> </samlp:AuthnRequest> 代码 private string GetSAMLHttpRedirectUri(string idpUri) { var saml = string.Format(SAMLRequest,Guid.NewGuid()); var bytes = Encoding.UTF8.GetBytes(saml); using (var output = new MemoryStream()) { using (var zip = new DeflaterOutputStream(output)) { zip.Write(bytes,bytes.Length); } var base64 = Convert.ToBase64String(output.ToArray()); var urlEncode = HttpUtility.UrlEncode(base64); return string.Concat(idpUri,"?SAMLRequest=",urlEncode); } } 我怀疑压缩是不知何故的.我正在使用SharpZipLib中的DeflaterOutputStream类,它应该实现行业标准的deflate-algorithm,所以也许这里有一些设置我错了? 编码输出可以使用此SAML2.0 Debugger(它是一个有用的在线转换工具)进行测试.当我使用这个工具对我的输出进行解码时,它会显示为废话. 因此,问题是:您是否知道如何将SAML字符串转换为正确缩放和编码的SAMLRequest查询参数? 谢谢 编辑1 下面接受的答案给出了问题的答案.以下是所有后续评论和答案所纠正的最终代码. 编码SAMLRequest – 工作代码 private string GenerateSAMLRequestParam() { var saml = string.Format(SAMLRequest,Guid.NewGuid()); var bytes = Encoding.UTF8.GetBytes(saml); using (var output = new MemoryStream()) { using (var zip = new DeflateStream(output,CompressionMode.Compress)) { zip.Write(bytes,bytes.Length); } var base64 = Convert.ToBase64String(output.ToArray()); return HttpUtility.UrlEncode(base64); } } SAMLRequest变量包含此问题顶部显示的SAML. 解码SAMLResponse – 工作代码 private string DecodeSAMLResponse(string response) { var utf8 = Encoding.UTF8; var bytes = utf8.GetBytes(response); using (var output = new MemoryStream()) { using (new DeflateStream(output,CompressionMode.Decompress)) { output.Write(bytes,bytes.Length); } var base64 = utf8.GetString(output.ToArray()); return utf8.GetString(Convert.FromBase64String(base64)); } } 解决方法
我刚刚运行以下代码与您的示例SAML:
var saml = string.Format(sample,Guid.NewGuid()); var bytes = Encoding.UTF8.GetBytes(saml); string middle; using (var output = new MemoryStream()) { using (var zip = new DeflaterOutputStream(output)) zip.Write(bytes,bytes.Length); middle = Convert.ToBase64String(output.ToArray()); } string decoded; using (var input = new MemoryStream(Convert.FromBase64String(middle))) using (var unzip = new InflaterInputStream(input)) using (var reader = new StreamReader(unzip,Encoding.UTF8)) decoded = reader.ReadToEnd(); bool test = decoded == saml; 测试变量是true.这意味着zip / base64 / unbase64 /解压缩往返执行正常.错误必须在以后出现.也许URLEncoder破坏他们?你可以尝试类似的urlencode /解码测试吗?另外,检查结果是多久.生成的URL可能由于其长度而被截断. (编辑:我已经添加了一个StreamReader而不是读数组.早期我的示例使用bytes.Length来准备缓冲区,并且可能会损坏测试现在阅读仅使用来自压缩流的信息) 编辑: var saml = string.Format(sample,Guid.NewGuid()); var bytes = Encoding.UTF8.GetBytes(saml); string middle; using (var output = new MemoryStream()) { using (var zip = new DeflateStream(output,CompressionMode.Compress)) zip.Write(bytes,bytes.Length); middle = Convert.ToBase64String(output.ToArray()); } // MIDDLE is the thing that should be now UrlEncode'd string decoded; using (var input = new MemoryStream(Convert.FromBase64String(middle))) using (var unzip = new DeflateStream(input,CompressionMode.Decompress)) using (var reader = new StreamReader(unzip,Encoding.UTF8)) decoded = reader.ReadToEnd(); bool test = decoded == saml; 此代码生成一个中间变量,一次是UrlEncoded,正确地通过调试器. DeflateStream来自标准的.Net的System.IO.Compression命名空间.我没有丝毫的想法为什么SharpZip的Deflate不被“调试器”站点接受.压缩是不可否认的,因为它可以正确地解压缩数据.它只是在算法中有一些区别,但是我不知道这个放气和放气的区别是什么? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |