2012-08-23 10 views
13

का उपयोग कर 'HTTP रीडायरेक्ट बाइंडिंग' SAML अनुरोध को सही ढंग से कैसे तैयार करूं, मुझे HTTP रीडायरेक्ट बाइंडिंग विधि का उपयोग करके एक एसपी शुरू किया SAML 2.0 प्रमाणीकरण लेनदेन बनाना होगा। यह पता चला है कि यह काफी आसान है। बस आईडीपी यूआरआई प्राप्त करें और एक क्वेरी-स्ट्रिंग पैरा SAMLRequest को संयोजित करें। परम एक्सएमएल का एन्कोडेड ब्लॉक है जो SAML अनुरोध का वर्णन करता है। अब तक सब ठीक है।मैं सी #

समस्या तब होती है जब SAML को क्वेरी स्ट्रिंग पैरा में परिवर्तित किया जाता है। मेरा मानना ​​है कि तैयारी की इस प्रक्रिया को होना चाहिए:

  1. , SAML- स्ट्रिंग बिल्ड
  2. कम्प्रेस इस स्ट्रिंग
  3. बेस 64 एन्कोड स्ट्रिंग
  4. UrlEncode स्ट्रिंग।

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, 0, bytes.Length); 
     } 
     var base64 = Convert.ToBase64String(output.ToArray()); 
     var urlEncode = HttpUtility.UrlEncode(base64); 
     return string.Concat(idpUri, "?SAMLRequest=", urlEncode); 
    } 
} 

मुझे लगता है संपीड़न इसके लिए जिम्मेदार किसी भी तरह है। मैं DeflaterOutputStream कक्षा का उपयोग SharpZipLib से कर रहा हूं जो कि एक उद्योग मानक डिफ्लेट-एल्गोरिदम लागू करने वाला है, इसलिए शायद यहां कुछ सेटिंग्स हैं जिनमें मुझे गलत है?

एन्कोडेड आउटपुट का परीक्षण इस SAML2.0 Debugger (इसका एक उपयोगी ऑनलाइन रूपांतरण टूल) का उपयोग करके किया जा सकता है। जब मैं इस उपकरण का उपयोग करके अपना आउटपुट डीकोड करता हूं तो यह बकवास के रूप में आता है।

इसलिए सवाल यह है: क्या आप जानते हैं कि SAML स्ट्रिंग को सही ढंग से डिफलेटेड और एन्कोडेड SAMLRequest क्वेरी-param में कैसे परिवर्तित किया जाए?

आप

संपादित करें 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, 0, 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, 0, bytes.Length); 
     } 
     var base64 = utf8.GetString(output.ToArray()); 
     return utf8.GetString(Convert.FromBase64String(base64)); 
    } 
} 
+0

मैं आपके "डीकोड SAMLResponse - वर्किंग कोड" का उपयोग करने में असमर्थ था जिस तरह से लिखा गया है। मुझे इनपुट मेमोरीस्ट्रीम से इनपुट अलग करना पड़ा। मुझे DeflateStream करने से पहले UrlDecode और Convert.FromBase64String (...) भी करना पड़ा। बस सोचा कि अगर मैं अगले व्यक्ति की मदद करता हूं तो मैं एक नोट बनाउंगा। –

+0

क्या आप अपना कामकाजी कोड पोस्ट कर सकते हैं। – biofractal

+0

हे रैंडल, क्या आप "डीकोड SAMLResponse - वर्किंग कोड" में किए गए परिवर्तनों के लिए कोड प्रदान कर सकते हैं? यह बहुत सराहना की जाएगी! धन्यवाद – Naner

उत्तर

11

मैंने सिर्फ अपने उदाहरण 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, 0, 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 है। इसका मतलब है कि ज़िप/बेस 64/unbase64/unzip roundtrip सही ढंग से निष्पादित करता है। त्रुटि बाद में होनी चाहिए। शायद URLEncoder उन्हें नष्ट कर देता है? क्या आप समान यूरेनकोड/डीकोड परीक्षण का प्रयास कर सकते हैं? साथ ही, जांच करें कि परिणाम कितना समय है। यह संभव हो सकता है कि परिणामी यूआरएल इसकी लंबाई के कारण छोटा कर दिया गया हो।

(संपादित करें: मैंने सरणी को पढ़ने के बजाय स्ट्रीमरडर जोड़ा है। इससे पहले मेरा नमूना बाइट्स का उपयोग करता था। बफर तैयार करने के लिए लम्बाई और परीक्षण को नुकसान पहुंचा सकता है। अब पढ़ने केवल संपीड़ित धारा से जानकारी का उपयोग करती है)

संपादित करें:

 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, 0, 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; 

इस कोड, एक middle चर, कि एक बार urlencoded है पैदा करता है डिबगर के माध्यम से ठीक से गुजरता है। DeflateStream मानक से आता है .Net's System.IO.Compression नामस्थान। मेरे पास थोड़ा सा विचार नहीं है कि क्यों SharpZip के Deflate 'डीबगर' साइट द्वारा स्वीकार नहीं किया जाता है। यह अविश्वसनीय है कि संपीड़न काम करता है, क्योंकि यह डेटा को ठीक से डिकंप्रेस करने का प्रबंधन करता है .. इसे एल्गोरिदम में कुछ अंतर होना चाहिए, लेकिन मैं यह नहीं बता सकता कि इस डिफ्लेट और डिफ्लेट के बीच क्या अंतर है, डी ओह।

+0

आपके द्वारा प्रदान की गई डीबगर साइट एन्कोडेड संदेश का एक उदाहरण प्रदर्शित करती है। मैंने इसे डिफ्लेट और जीज़िप के साथ डिकंप्रेस करने की कोशिश की है - और यह संभव नहीं था .. नेट की GZipStream भी इसे डिकंप्रेस करने का प्रबंधन नहीं करता .. यह संपीड़न एल्गोरिदम इसका उपयोग करता है? – quetzalcoatl

+0

मुझे एक कंप्रेसर मिला है जो नमूना साइट के साथ काम करता है, और मैंने अभी तक जवाब अपडेट किया है। कृपया अंतिम भाग को दोबारा पढ़ें :) – quetzalcoatl

+0

महान काम। आपका कोड खूबसूरती से काम करता है। धन्यवाद :-) – biofractal

6

शीर्ष पर दिए गए प्रश्न में "डीकोड SAMLResponse - वर्किंग कोड" अनुभाग है, लेकिन वह कोड टूटा हुआ लग रहा था। कुछ चीजों की कोशिश करने के बाद, मैंने पाया कि वह एक ही समय में एक ही स्ट्रीम को पढ़ने और लिखने की कोशिश कर रहा था।

एनकोड SAML प्रमाणीकरण अनुरोध::

public static string EncodeSamlAuthnRequest(this string authnRequest) { 
    var bytes = Encoding.UTF8.GetBytes(authnRequest); 
    using (var output = new MemoryStream()) { 
     using (var zip = new DeflateStream(output, CompressionMode.Compress)) { 
     zip.Write(bytes, 0, bytes.Length); 
     } 
     var base64 = Convert.ToBase64String(output.ToArray()); 
     return HttpUtility.UrlEncode(base64); 
    } 
    } 

डिकोड SAML प्रमाणीकरण मैं पढ़ने को अलग करने और स्ट्रीम लिख और यहाँ है मेरे समाधान (मैं सुविधा और स्पष्टता के लिए अनुरोध अनुभाग प्रदान कर रहा हूँ) द्वारा यह फिर से काम प्रतिक्रिया:

public static string DecodeSamlAuthnRequest(this string encodedAuthnRequest) { 
    var utf8 = Encoding.UTF8; 
    var bytes = Convert.FromBase64String(HttpUtility.UrlDecode(encodedAuthnRequest)); 
    using (var output = new MemoryStream()) { 
    using (var input = new MemoryStream(bytes)) { 
     using (var unzip = new DeflateStream(input, CompressionMode.Decompress)) { 
     unzip.CopyTo(output, bytes.Length); 
     unzip.Close(); 
     } 
     return utf8.GetString(output.ToArray()); 
    } 
    } 
}