How to encrypt request string id in MVC 4 ActionLink

How can I pass the encrypted identifier to ActionLink . Here is what I wrote on my view :

 @model IEnumerable<forumAPP.tblTechnology> @foreach (var item in Model) { string techName=item.TechName; @Html.ActionLink(techName, "Details","Home", new { TopicID = item.TechID },null) // Here I would like to encrypt the TopicID <br /> <br /> @Html.DisplayFor(modelItem => item.TechDesc) } 
+7
source share
3 answers

Here are some simple methods you can use for encoding / decoding. The encoded value is not safe, and as you can see, decoding is trivial. If your goal is to confuse the identifier, this will work. If you need to protect him, you must take a different approach.

 public string Encode( string encodeMe ) { byte[] encoded = System.Text.Encoding.UTF8.GetBytes( encodeMe ); return Convert.ToBase64String( encoded ); } public static string Decode( string decodeMe ) { byte[] encoded = Convert.FromBase64String( decodeMe ); return System.Text.Encoding.UTF8.GetString( encoded ); } 

So, you can place these methods in your controller and pass the encoded TechId to the view using viewBag

 int techId = 1; var encoded = Encode(id.ToString()); ViewBag.Encoded = encoded; 

And then use it in your link

 @Html.ActionLink(techName, "Details","Home", new { TopicID = ViewBag.Encoded },null) 

(Although you should consider using a view model. ViewBag, while a convenient and easy way to pass data to a view, is not considered best practice. Become comfortable with view models and strongly typed mvc views life is much easier in the future. Not let alone create cleaner and more convenient code for those who follow you.)

+17
source

Add folder with two classes

Class 1: EncryptedActionParameterAttribute

 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Web; using System.Web.Mvc; namespace MVCInvoicClient.Extensions { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class EncryptedActionParameterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { Dictionary<string, object> decryptedParameters = new Dictionary<string, object>(); if (HttpContext.Current.Request.QueryString.Get("q") != null) { string encryptedQueryString = HttpContext.Current.Request.QueryString.Get("q"); string decrptedString = Decrypt(encryptedQueryString.ToString()); string[] paramsArrs = decrptedString.Split('?'); for (int i = 0; i < paramsArrs.Length; i++) { string[] paramArr = paramsArrs[i].Split('='); decryptedParameters.Add(paramArr[0], Convert.ToInt32(paramArr[1])); } } for (int i = 0; i < decryptedParameters.Count; i++) { filterContext.ActionParameters[decryptedParameters.Keys.ElementAt(i)] = decryptedParameters.Values.ElementAt(i); } base.OnActionExecuting(filterContext); } private string Decrypt(string encryptedText) { string key = "jdsg432387#"; byte[] DecryptKey = { }; byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 }; byte[] inputByte = new byte[encryptedText.Length]; DecryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8)); DESCryptoServiceProvider des = new DESCryptoServiceProvider(); inputByte = Convert.FromBase64String(encryptedText); MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(DecryptKey, IV), CryptoStreamMode.Write); cs.Write(inputByte, 0, inputByte.Length); cs.FlushFinalBlock(); System.Text.Encoding encoding = System.Text.Encoding.UTF8; return encoding.GetString(ms.ToArray()); } } } 

Class 2: MyExtensions

 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCInvoicClient.Extensions { public static class MyExtensions { public static MvcHtmlString EncodedActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes) { string queryString = string.Empty; string htmlAttributesString = string.Empty; if (routeValues != null) { RouteValueDictionary d = new RouteValueDictionary(routeValues); for (int i = 0; i < d.Keys.Count; i++) { if (i > 0) { queryString += "?"; } queryString += d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i); } } if (htmlAttributes != null) { RouteValueDictionary d = new RouteValueDictionary(htmlAttributes); for (int i = 0; i < d.Keys.Count; i++) { htmlAttributesString += " " + d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i); } } //<a href="/Answer?questionId=14">What is Entity Framework??</a> StringBuilder ancor = new StringBuilder(); ancor.Append("<a "); if (htmlAttributesString != string.Empty) { ancor.Append(htmlAttributesString); } ancor.Append(" href='"); if (controllerName != string.Empty) { ancor.Append("/" + controllerName); } if (actionName != "Index") { ancor.Append("/" + actionName); } if (queryString != string.Empty) { ancor.Append("?q=" + Encrypt(queryString)); } ancor.Append("'"); ancor.Append(">"); ancor.Append(linkText); ancor.Append("</a>"); return new MvcHtmlString(ancor.ToString()); } private static string Encrypt(string plainText) { string key = "jdsg432387#"; byte[] EncryptKey = { }; byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 }; EncryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8)); DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] inputByte = Encoding.UTF8.GetBytes(plainText); MemoryStream mStream = new MemoryStream(); CryptoStream cStream = new CryptoStream(mStream, des.CreateEncryptor(EncryptKey, IV), CryptoStreamMode.Write); cStream.Write(inputByte, 0, inputByte.Length); cStream.FlushFinalBlock(); return Convert.ToBase64String(mStream.ToArray()); } } } 

controller

 Add this line above the controller class Example for your Index [EncryptedActionParameter] 

In your view

  @Html.EncodedActionLink("Download Invoice", "FileDownload","DataFiles", new { id = item.DataFilesID }, null) 

add using statement

 @using MVCInvoicClient.Extensions 
+2
source

I came across this looking for a safe way to do this. If someone wants to do this safely, you can use MvcSerializer (I found it in the MVC futures 3 project, I'm not sure if it is included in MVC 4). For example:

 (new MvcSerializer()).Serialize(<Your data here>, SerializationMode.EncryptedAndSigned) 

And then, to cancel the process ...

 (new MvcSerializer()).Deserialize(<Serialized data here>, SerializationMode.EncryptedAndSigned) 

This is great because without any extra effort it encrypts and signs the data. The futures project also includes some attributes so that this happens automatically when the model is linked.

0
source

All Articles