C# MVC 查询字符串编码和解码

Posted

技术标签:

【中文标题】C# MVC 查询字符串编码和解码【英文标题】:C# MVC Query String Encoding and Decoding 【发布时间】:2017-11-01 00:13:33 【问题描述】:

我想对 url 参数进行编码和解码。

javascript中调用函数

var url = '/Demo/Demo?id=58';
$(location).attr('href', url)

当前url参数

www.example.com/Demo/Demo?id=58

演示控制器中的代码

public ActionResult Demo(int id)

   return view();

我希望上面的 url 像 bolow 行一样更改

www.example.com/Demo/Demo?id=Sff5f8ddg

这样 id 值将是机密的。编码和解码的最佳方式是什么。

注意:我们通过锚标记、ajax 和 jquery 调用方法。 Base64以外的编码和解码

除了Base64编码和解码之外,还有其他加密方法,如javascript中的加密和C#方法中的解密

【问题讨论】:

如果传递机密参数,则不使用查询字符串参数,但可以使用后参数 分享一些post参数的例子 你最喜欢的搜索引擎宕机了吗? 在 url 中编码查询字符串的最佳方式 这取决于 (a) 如果您只是想混淆您的参数或 (b) 保护您的参数。我会遵循@hazzik 所说的并使用 GUID。如果user N 存在问题,需要适当的权限才能访问该操作,那么您需要在服务器端使用传递的 ID 执行任何操作之前检查这一点。 【参考方案1】:

这样 id 值将是机密的。编码和解码的最佳方式是什么。

不会的。至少在你试图做到的方式上。一旦您对 [internal] id 进行编码,它就会成为该条目的公共 id。用户使用哪个 id 无关紧要:58Sff5f8ddg,因为它将引用系统中的相同条目。如果您使用的是无盐算法,它只会阻止不那么成熟的用户发现您系统中的其他条目。

据我了解,您要解决的问题是 - 如何通过为某些条目设置 id 来使其他条目无法被发现。例如,如果用户有条目 58 的 url,他们应该无法找到条目 57 和 59。

解决方案是:使用 GUID 作为条目的 ID。

此外,您需要确保已为您的条目实施了适当的访问控制。

【讨论】:

由于 GUID 与 ID 相关联并且任何人都可以识别 GUID,因此检测到所有可用的 GUID 只是时间问题。 @RuardvanElburg 对不起,WAT?祝你好运...the number of random version 4 UUIDs which need to be generated in order to have a 50% probability of at least one collision is 2.71 quintillion [...] This number is equivalent to generating 1 billion UUIDs per second for about 85 years。我可以得到你的许可打印你的评论并贴在我的墙上吗? 另外,为什么我什至需要将 GUID 链接到任意整数 ID?【参考方案2】:

在javascript中,你可以使用

var str = "Hello World!";
var enc = window.btoa(str);
var dec = window.atob(enc);

res 的结果是:

Encoded String: SGVsbG8gV29ybGQh
Decoded String: Hello World!

这个例子展示了如何使用 RijndaelManaged 进行加密解密。

 public static class Cryptography
    

        private static readonly byte[] _key =  0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03 ;
        private static readonly byte[] _iV =  0x10, 0x11, 0x12, 0x13, 0x10, 0x11, 0x12, 0x13, 0x10, 0x11, 0x12, 0x13, 0x10, 0x11, 0x12, 0x13 ;

        #region Encryption


        public static string Encrypt(this string inputText)
        
            string _encryptString = string.Empty;
            if (string.IsNullOrEmpty(inputText))
                return string.Empty;
            else
            
                ASCIIEncoding textConverter = new ASCIIEncoding();
                RijndaelManaged myRijndael = new RijndaelManaged();

                ICryptoTransform encryptor = myRijndael.CreateEncryptor(_key, _iV);
                MemoryStream msEncrypt = new MemoryStream();
                CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
                byte[] toEncrypt = textConverter.GetBytes(inputText);
                csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
                csEncrypt.FlushFinalBlock();
                _encryptString = Convert.ToBase64String(msEncrypt.ToArray()).Replace(" ", "+");
                return _encryptString;
            
        

        public static string Decrypt(this string inputText)
        
            string text = inputText;
            try
            
                if (string.IsNullOrEmpty(inputText))
                    return string.Empty;
                else
                
                    inputText = inputText.Replace(" ", "+");

                    byte[] encrypted = Convert.FromBase64String(inputText);
                    ASCIIEncoding textConverter = new ASCIIEncoding();
                    RijndaelManaged myRijndael = new RijndaelManaged();

                    ICryptoTransform decryptor = myRijndael.CreateDecryptor(_key, _iV);
                    MemoryStream msDecrypt = new MemoryStream(encrypted);
                    CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
                    byte[] fromEncrypt = new byte[encrypted.Length];
                    csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
                    return textConverter.GetString(fromEncrypt).TrimEnd('\x0');
                
            
            catch (FormatException)
            
                return "";
            
            catch (Exception ex)
            
                return text;
            
        



        #endregion Encryption

    

现在在控制器中加密解密就像

 "id".Encrypt();///
  "encryptID".Decrypt();

【讨论】:

你可以分享javascript和控制器方法的示例代码 RijndaelManaged myRijndael = new RijndaelManaged();显示错误 您需要添加命名空间“使用 System.Security.Cryptography” 方法 -> public ActionResult Demo(int id)。那么 int 数据类型将返回错误 您必须将 int 值转换为字符串,如 "58".Encrypt()【参考方案3】:
var id=Encrypt(YourID);
var id=Decrypt(YourID);

  using System.Security.Cryptography;

public static string Encrypt(string inputText)
    
        string encryptionkey = "SAUW193BX628TD57";
        byte[] keybytes = Encoding.ASCII.GetBytes(encryptionkey.Length.ToString());
        RijndaelManaged rijndaelCipher = new RijndaelManaged();
        byte[] plainText = Encoding.Unicode.GetBytes(inputText);
        PasswordDeriveBytes pwdbytes = new PasswordDeriveBytes(encryptionkey, keybytes);
        using (ICryptoTransform encryptrans = rijndaelCipher.CreateEncryptor(pwdbytes.GetBytes(32), pwdbytes.GetBytes(16)))
        
            using (MemoryStream mstrm = new MemoryStream())
            
                using (CryptoStream cryptstm = new CryptoStream(mstrm, encryptrans, CryptoStreamMode.Write))
                
                cryptstm.Write(plainText, 0, plainText.Length);
                cryptstm.Close();
                return Convert.ToBase64String(mstrm.ToArray());
                
            
        
    

public static string Decrypt(string encryptText)

    string encryptionkey = "SAUW193BX628TD57";
    byte[] keybytes = Encoding.ASCII.GetBytes(encryptionkey.Length.ToString());
    RijndaelManaged rijndaelCipher = new RijndaelManaged();
    byte[] encryptedData = Convert.FromBase64String(encryptText.Replace(" ", "+"));
    PasswordDeriveBytes pwdbytes = new PasswordDeriveBytes(encryptionkey, keybytes);
    using (ICryptoTransform decryptrans = rijndaelCipher.CreateDecryptor(pwdbytes.GetBytes(32), pwdbytes.GetBytes(16)))
    
        using (MemoryStream mstrm = new MemoryStream(encryptedData))
        
            using (CryptoStream cryptstm = new CryptoStream(mstrm, decryptrans, CryptoStreamMode.Read))
            
            byte[] plainText = new byte[encryptedData.Length];
            int decryptedCount = cryptstm.Read(plainText, 0, plainText.Length);
            return Encoding.Unicode.GetString(plainText, 0, decryptedCount);
            
        
    

【讨论】:

【参考方案4】:

从您的问题中我可以理解的是,您希望限制用户能够知道 id 参数的确切值。

但这无济于事,因为您的浏览器/客户端已经拥有该值。 所以你在你的客户上有 id 并且你想限制你的客户知道它的价值。 普通开发人员(任何编写代码的人)都可以使用浏览器的开发人员工具访问您的价值。 所以没有任何好处。

另一种方法是您从服务器本身发送加密的 id。 为此,您可以使用@Karan Singh 提供的解决方案。 或者您想要探索的任何其他选项都取决于您。

一个建议尝试使用一种无​​法反向完成的加密方法。这将增加处理开销,因为您必须首先从 DB 加密您的 Id,然后将其与客户端发送的值匹配。

谢谢。

【讨论】:

【参考方案5】:

您可以简单地使用 jquery 函数,例如:

var encodedUrl = encodeURIComponent("your url"); //'/Demo/Demo?id=58'; console.log(encodedUrl);

谢谢

【讨论】:

它正在返回“'/' 应用程序中的服务器错误。”点击时 我得到了一个完美的结果,例如:%2FDemo%2FDemo%3Fid%3D58 id 58 可见【参考方案6】:

如果您要做的是从呈现的内容(客户端)中隐藏 58,那么您需要在后端实现加密/解密方案并根据需要将该值从/传递到客户端.

当您向客户端提供数据时,您的服务器端代码会将 58 加密为一些字符串,以隐藏真实值并将其传递给客户端。

当客户端向您发出请求时,它应该使用您之前提供的加密字符串,并且您的服务器应该将其解密成它可以使用的东西。

您不需要 JavaScript 来加密和 C# 来解密这些值。 JavaScript 部分应该始终使用加密的 id,因为它是在客户端执行 事后 的脚本。服务器端如何使用该值是客户端 JavaScript 不需要了解的内部方面。

【讨论】:

【参考方案7】:

你好,我想你想创建一个脾气暴躁的查询字符串Download the code from github repository

【讨论】:

【参考方案8】:

控制器:

[HttpPost]
        public ActionResult SubmitInputTest(int id)  
            //your code 
            //do stuff

            return RedirectToAction("index");
        

在你看来(cshtml):

<form id="frmToSubmit" action="<controller>/SubmitInputTest">
 <hidden id="id" name="id"/>
</form>

在你的 javascript 中:

$('#id').attr('value', [your ID Value]);
$('#frmToSubmit').submit();

【讨论】:

它不是一种形式。只是 标签 你在哪里指定要使用标签???如果你执行一个 javascript 函数,你可以按需创建一个表单并发布它 我不会使用表单

以上是关于C# MVC 查询字符串编码和解码的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 java 对从 javascript 到 servletpage 的查询字符串进行编码和解码?

JS中编码和解码的总结

前端JS后台C#编码解码。

如何解码用 JavaScriptStringEncoded 编码的字符串?

2018-07-17 Base64解码与编码

SSE图像算法优化系列三十一:Base64编码和解码算法的指令集优化(C#自带函数的3到4倍速度)。