2009-05-21 32 views
10

में एक URL में एक आईडी को कूटबद्ध मैं यूआरएल में एन्क्रिप्टेड आईडी सांकेतिक शब्दों में बदलना करने का प्रयास कर रहा हूँ। इस तरह: http://www.calemadr.com/Membership/Welcome/9xCnCLIwzxzBuPEjqJFxC6XJdAZqQsIDqNrRUJoW6229IIeeL4eXl5n1cnYapg+NASP.NET MVC

हालांकि, यह या तो सही ढंग से एन्कोड नहीं करता और मैं एन्क्रिप्शन में स्लैश '/' मिलता है या मैं आईआईएस से प्राप्त करते हैं और त्रुटि: अनुरोध को छानने मॉड्यूल एक अनुरोध शामिल है कि अस्वीकार करने के लिए कॉन्फ़िगर किया गया है एक डबल एस्केप अनुक्रम।

मैं अलग एन्कोडिंग की कोशिश की है, प्रत्येक में विफल रहता है:

  • HttpUtility.HtmlEncode
  • HttpUtility.UrlEncode
  • HttpUtility.UrlPathEncode
  • HttpUtility.UrlEncodeUnicode

अद्यतन

समस्या तब थी जब मैंने एक ग्रिड एन्क्रिप्ट किया और इसे बेस 64 स्ट्रिंग में परिवर्तित कर दिया, इसमें असुरक्षित यूआरएल वर्ण होंगे। बेशक जब मैंने असुरक्षित अक्षर आईआईएस (7.5/विंडोज 7) वाले यूआरएल पर नेविगेट करने की कोशिश की तो वह उड़ाएगा। यूआरएल बेस 64 IIS में स्ट्रिंग को उठाएंगे और त्रुटि एन्क्रिप्टेड (अनुरोध को छानने मॉड्यूल एक अनुरोध है कि एक डबल एस्केप अनुक्रम है अस्वीकार करने के लिए कॉन्फ़िगर किया गया है।) एन्कोडिंग। मुझे यकीन नहीं है कि यह डबल एन्कोडेड तारों का पता कैसे लगाता है लेकिन ऐसा हुआ।

बेस 64 एन्क्रिप्टेड स्ट्रिंग को एन्कोड करने के लिए उपरोक्त विधियों को आजमाने के बाद। मैंने बेस 64 एन्कोडिंग को हटाने का फैसला किया। हालांकि यह एन्क्रिप्टेड पाठ को बाइट [] के रूप में छोड़ देता है। मैंने बाइट [] को UrlEncoding करने की कोशिश की, यह httpUtility.Encode विधि को लटकाने वाले अधिभारों में से एक है। फिर, जबकि यह यूआरएल इनकोडिंग किया गया था, आईआईएस इसे पसंद नहीं किया और एक परोसा "पृष्ठ नहीं मिला।"

नेट के चारों ओर खुदाई के बाद मैं HexEncoding/Decoding कक्षा में आया। एन्क्रिप्टेड बाइट्स में हेक्स एन्कोडिंग को लागू करने से चाल चल रही है। आउटपुट यूआरएल सुरक्षित है। दूसरी तरफ, मुझे हेक्स तारों को डीकोड करने और डिक्रिप्ट करने में कोई समस्या नहीं है।

+1

आपका अपडेट रास्ता जवाब से बेहतर है। और अगर आप Base64 इनकोडिंग यूआरएल है कि सुरक्षित हैं चाहते हैं, यह पढ़ें: http://stackoverflow.com/a/10858198/237858 – kape123

उत्तर

7

मैंने पूर्ण स्रोत कोड सहित इस विषय के बारे में एक छोटा ब्लॉग post लिखा था।

मैं आधार वर्ग का एक बड़ा सेट पाया इस हल करने के लिए, लेकिन ज्यादातर भाग के लिए यह करने के लिए नीचे आता है:

यह आप एन्क्रिप्ट और एक 16 वर्ण कुंजी का उपयोग कर क्वेरी स्ट्रिंग रूप में संग्रहीत डेटा को डिक्रिप्ट करने में सक्षम बनाता है कक्षा प्रथम। इस वर्ग को की 16 चर कुंजी की आवश्यकता होती है ताकि एन्क्रिप्शन और एन्क्रिप्ट करने के लिए कोई मान किया जा सके। यदि आप आवश्यक हो तो एक समाप्ति मूल्य भी सेट कर सकते हैं।

using System.Collections.Specialized; 
using System.Security; 
using System.Text; 
using System.Web; 
using EncryptionMVC.Security.Encryption.Utility.Interfaces; 
using EncryptionMVC.Security.Encryption.Utility; 
namespace Security.Encryption.QueryString 
{ 
    /// 
    /// Provides a secure means for transfering data within a query string. 
    /// 
    public class SecureQueryString : NameValueCollection 
    { 

     private string timeStampKey = '__TS__'; 
     private string dateFormat = 'G'; 
     private IEncryptionUtility mEncryptionUtil; 
     private DateTime m_expireTime = DateTime.MaxValue; 

     /// 
     /// Creates an instance with a specified key. 
     /// 
     /// The key used for cryptographic functions, required 16 chars in length. 
     public SecureQueryString(string key) : base() 
     { 
      mEncryptionUtil = new EncryptionUtility(key); 
     } 

     /// 
     /// Creates an instance with a specified key and an encrypted query string. 
     /// 
     /// The key used for cryptographic functions, required 16 chars in length. 
     /// An encrypted query string generated by a instance. 
     public SecureQueryString(string key, string queryString) : this(key) 
     { 
      Deserialize(DecryptAndVerify(queryString)); 
      CheckExpiration(); 
     } 

     /// 
     /// Returns a encrypted query string. 
     /// 
     /// 
     public override string ToString() 
     { 
      return EncryptAndSign(Serialize()); 
     } 

     private void Deserialize(string queryString) 
     { 
      string[] nameValuePairs = queryString.Split('&'); 
      for (int i = 0; i <= nameValuePairs.Length - 1; i++) { 
       string[] nameValue = nameValuePairs(i).Split('='); 
       if (nameValue.Length == 2) { 
        base.Add(nameValue(0), nameValue(1)); 
       } 
      } 

      if (base.GetValues(timeStampKey) != null) { 
       string[] strExpireTime = base.GetValues(timeStampKey); 
       m_expireTime = Convert.ToDateTime(strExpireTime(0)); 
      } 
     } 

     private string Serialize() 
     { 
      StringBuilder sb = new StringBuilder(); 
      foreach (string key in base.AllKeys) { 
       sb.Append(key); 
       sb.Append('='); 
       sb.Append(base.GetValues(key)(0).ToString()); 
       sb.Append('&'); 
      } 

      sb.Append(timeStampKey); 
      sb.Append('='); 
      sb.Append(m_expireTime.ToString(dateFormat)); 

      return sb.ToString(); 
     } 

     private string DecryptAndVerify(string input) 
     { 
      return mEncryptionUtil.Decrypt(input); 
     } 

     private string EncryptAndSign(string input) 
     { 
      return mEncryptionUtil.Encrypt(input); 
     } 

     private void CheckExpiration() 
     { 
      if (DateTime.Compare(m_expireTime, DateTime.Now) < 0) { 
       throw new ExpiredQueryStringException(); 
      } 
     } 

     /// 
     /// Gets or sets the timestamp in which this string should expire 
     /// 
     public DateTime ExpireTime { 
      get { return m_expireTime; } 
      set { m_expireTime = value; } 
     } 
    } 
} 

कुछ मूल्य एन्क्रिप्ट और यह MVC में एक और कार्रवाई आप नीचे की तरह कुछ करना होगा करने के लिए आगे बढ़ने के लिए।

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Index(FormCollection collection) 
{ 
    SecureQueryString qs = new SecureQueryString(mKey); 

    qs('YourName') = collection('name'); 
    qs.ExpireTime = DateTime.Now.AddMinutes(2); 

    Response.Redirect('Home.aspx/About?data=' + HttpUtility.UrlEncode(qs.ToString())); 
} 

कार्रवाई है कि हम करने के लिए, तो आप इस एक ही कुंजी और क्वेरी स्ट्रिंग मान ही उसे डिक्रिप्ट करने के लिए की आवश्यकता होगी अनुप्रेषित में। ध्यान रखें कि यदि आपके पास सही कुंजी नहीं है या यदि आप समाप्ति के बाद मूल्य को डिक्रिप्ट करने का प्रयास करते हैं, तो कक्षा अपवाद फेंक देगी।

public ActionResult About() 
{ 
    if (Request('data') != null) { 
     try { 
      SecureQueryString qs = new SecureQueryString(mKey, Request('data')); 

      ViewData('Message') = 'Your name is ' + qs('YourName'); 
     } 
     catch (Exception ex) { 

     } 
    } 
    return View(); 
} 

मैं अधिक समय खर्च नहीं किया था गहराई में स्रोत समझा क्योंकि यह बहुत देर से मैं यह लिखा गया है। यह भी ध्यान रखें कि यह से पहले मेरे परीक्षण के पहले दिन था ... (लेकिन यह काम करने के लिए प्रतीत होता है)

हमेशा के रूप में, इस नमूने के लिए source code डाउनलोड के लिए उपलब्ध है।

2

एन्क्रिप्टिंग और एन्कोडिंग के बीच एक अंतर है; उन विधियों को एन्क्रिप्टिंग के लिए नहीं था।

क्योंकि एन्क्रिप्शन ठीक है, और अविश्वसनीय रूप से गलत करने के लिए आसान प्राप्त करने के लिए (जबकि अभी भी बस के रूप में सही समाधान के रूप में "एन्क्रिप्टेड" देख) कठिन है, मेरा सुझाव है कि आप के बजाय GUID आईडी का उपयोग:

http://www.calemadr.com/.../ {6F0184E4- 80 9 एफ -4e30-8A5B-4DC144135A54}

SQL सर्वर के पास इस मामले के लिए अद्वितीय पहचानकर्ता प्रकार है।

+0

seconded। आईडी पर एन्क्रिप्शन का उपयोग करने में कोई बात नहीं है यदि उद्देश्य सिर्फ अपवित्रता है। – womp

+2

मेरी माफ़ी, मैं इस सवाल में पर्याप्त विस्तृत नहीं था। मैं यूआरएल सुरक्षित होने के लिए एन्क्रिप्टेड स्ट्रिंग को एन्कोड करने की कोशिश कर रहा हूं। विडंबना यह है कि, मैं ग्विड्स का उपयोग कर रहा हूं, उपर्युक्त एन्क्रिप्शन एक ग्रिड है। समस्या एक एन्क्रिप्टेड स्ट्रिंग एन्कोडिंग कर रही है जो आईआईएस को सुरक्षा चेतावनी फेंकने या निर्देशिका संरचना (स्लैश '/') दिखाई देती है @Womp- सिस्टम की प्रकृति के कारण मुझे आईडी को एन्क्रिप्ट करना है । –

+1

हम्म। फिर आप GUID क्यों एन्क्रिप्ट कर रहे हैं? यदि आप किसी ऐसे व्यक्ति के बारे में चिंतित हैं जो यूआरएल का पुन: उपयोग करने के लिए अधिकृत नहीं है, तो वे आपके द्वारा दिए गए यूआरएल का समान रूप से पुन: उपयोग कर सकते हैं। यदि आप किसी के बारे में चिंतित हैं * अनुमान लगा रहे हैं * किसी और के GUID ... कभी नहीं होने वाला। –

1

मुझे आश्चर्य है कि UrlEncode काम नहीं करता है। आपके एन्क्रिप्शन का आउटपुट कैसा दिखता है?

अपने ग्रिड को एन्क्रिप्ट करने के बाद, इसे Convert.ToBase64String विधि के साथ बेस 64 पर एन्कोड करने का प्रयास करें। फिर अपने यूआरएल में शामिल करने के लिए एक स्वीकार्य स्ट्रिंग बनाने के लिए बेस 64 स्ट्रिंग को यूआरएलएनकोड करें।

+2

यह बेहतर हो सकता है बस बदलने के लिए/और + के साथ -, यूआरएल के लिए और _ बजाय उन्हें urlencoding से। एक पानी का छींटा और जो है - - –

+0

लेकिन क्या आप भी unencode, तो फिर तुम जो कैसे पता होगा की जरूरत है एक स्लेश है? – CoderDennis

1

हम्म ... यह शायद कोई फर्क नहीं पड़ता है लेकिन आप एंटीएक्सएसएस लाइब्रेरी और यह URLEncode() विधि को आजमा सकते हैं।

http://www.codeplex.com/AntiXSS

HTHs, चार्ल्स

+0

मैंने पहले इस पुस्तकालय का उपयोग किया है। मैं इसे एक शॉट दूंगा। –

1

पता है कि यह आप के लिए अब और मायने रखती है लेकिन मैं सिर्फ अपने दम पर इस समस्या का समाधान नहीं है। मुझे urlencode डबल करना पड़ा।

उदाहरण के लिए

Server.UrlEncode (Server.UrlEncode (स्ट्रिंग एन्कोड करने के लिए))

समस्या यह है कि Request.Querystring (इनकोडिंग स्ट्रिंग) स्वचालित रूप से एक डिकोड जो एन्क्रिप्शन पंगा लेना है करता प्रतीत हो रहा है । काश मैं बेहतर समझा सकता हूं लेकिन मैं अभी भी थोड़ा उलझन में हूं

10

उपयोग HttpServerUtility.UrlTokenEncode और HttpServerUtility.UrlTokenDecode बाइट सरणी परिवर्तित करने के लिए URL सुरक्षित स्ट्रिंग के लिए।

C# Byte[] to Url Friendly String देखें।

+0

+1 लिंक के लिए धन्यवाद। –

2

यह पोस्ट पुराना हो सकता है लेकिन यहां आपके पास एक और समाधान है ... जब आप एन्क्रिप्ट करने जा रहे हैं। ToBase64String, यूआरएल एनकोड/डीकोड एन्क्रिप्टेड स्ट्रिंग को बदलता है।

डिकोड करने से पहले अपने encription पुस्तकालय (या समारोह) पर इस प्रयास करें:

Myencodedid.Replace(' ', '+') 

और फिर, डिक्रिप्शन के लिए जाना ..

1

सबसे पहले इस तरह एक वर्ग बनाने:

public class Encryption 
{ 
    public static string Encrypt(string clearText) 
    { 
     string EncryptionKey = "MAKV2SPBNI99212"; 
     byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); 
     using (Aes encryptor = Aes.Create()) 
     { 
      Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 
      encryptor.Key = pdb.GetBytes(32); 
      encryptor.IV = pdb.GetBytes(16); 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) 
       { 
        cs.Write(clearBytes, 0, clearBytes.Length); 
        cs.Close(); 
       } 
       clearText = Convert.ToBase64String(ms.ToArray()); 
      } 
     } 
     return clearText; 
    } 

    public static string Decrypt(string cipherText) 
    { 
     string EncryptionKey = "MAKV2SPBNI99212"; 
     byte[] cipherBytes = Convert.FromBase64String(cipherText); 
     using (Aes encryptor = Aes.Create()) 
     { 
      Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 
      encryptor.Key = pdb.GetBytes(32); 
      encryptor.IV = pdb.GetBytes(16); 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write)) 
       { 
        cs.Write(cipherBytes, 0, cipherBytes.Length); 
        cs.Close(); 
       } 
       cipherText = Encoding.Unicode.GetString(ms.ToArray()); 
      } 
     } 
     return cipherText; 
    } 
} 

नियंत्रक में, इस तरह इस Ecription वर्ग के लिए संदर्भ जोड़ें:

using testdemo.Models 

public ActionResult Index() { 
      return View(); 
     } 
     [HttpPost] 
     public ActionResult Index(string text) 
     { 
      if (Request["txtEncrypt"] != null) 
      { 
       string getEncryptionCode = Request["txtEncrypt"]; 
       string DecryptCode = Encryption.Decrypt(HttpUtility.UrlDecode(getEncryptionCode)); 
       ViewBag.GetDecryptCode = DecryptCode; 
       return View(); 
      } 
      else { 
       string getDecryptCode = Request["txtDecrypt"]; 
       string EncryptionCode = HttpUtility.UrlEncode(Encryption.Encrypt(getDecryptCode)); 
       ViewBag.GetEncryptionCode = EncryptionCode; 
       return View(); 
      } 

     } 

देखें में:

<h2>Decryption Code</h2> 
@using (Html.BeginForm()) 
{ 
    <table class="table-bordered table"> 
     <tr> 
      <th>Encryption Code</th> 
      <td><input type="text" id="txtEncrypt" name="txtEncrypt" placeholder="Enter Encryption Code" /></td> 
     </tr> 
     <tr> 
      <td colspan="2"> 
       <span style="color:red">@ViewBag.GetDecryptCode</span> 
      </td> 
     </tr> 
     <tr> 
       <td colspan="2"> 
        <input type="submit" id="btnEncrypt" name="btnEncrypt"value="Decrypt to Encrypt code" /> 
       </td> 
      </tr> 
    </table> 
} 
    <br /> 
    <br /> 
    <br /> 
    <h2>Encryption Code</h2> 
@using (Html.BeginForm()) 
{ 
    <table class="table-bordered table"> 
     <tr> 
      <th>Decryption Code</th> 
      <td><input type="text" id="txtDecrypt" name="txtDecrypt" placeholder="Enter Decryption Code" /></td> 
     </tr> 

     <tr> 
      <td colspan="2"> 
       <span style="color:red">@ViewBag.GetEncryptionCode</span> 
      </td> 
     </tr> 
     <tr> 
      <td colspan="2"> 
       <input type="submit" id="btnDecryt" name="btnDecryt" value="Encrypt to Decrypt code" /> 
      </td> 
     </tr> 
    </table> 
} 

मैं इस उपयोगी उम्मीद है।

+0

ओपी ने यूआरआई एन्क्रिप्शन के बारे में पूछा, सामान्य फॉर्म फ़ील्ड एन्क्रिप्शन नहीं – Fandango68