/ / ASP.NET MVC: Забезпечення редагування позицій з однаковим ідентифікатором елемента - asp.net-mvc, перевірка, цілісність даних

ASP.NET MVC: Забезпечення елемента "Редагування публікацій" того ж ідентифікатора предмета - asp.net-mvc, перевірка, цілісність даних

Я створюю набір CRUD-сторінок для редагування елемента за допомогою MVC, але мене бентежить питання про те, як я можу переконатися, що елемент, який редагує користувач, є тим самим елементом, який він публікує для оновлення.

В даний час у мене є Приховано помічник, який зберігає ItemID, який, звичайно, розміщує в EditItem дія, заповнюючи її модель, щоб я міг її оновити ...

Але що станеться, якщо вони увійдуть і відредагують цеприхований ідентифікатор і змінити його на щось інше? Я, звичайно, можу додати фільтр дій, щоб запобігти редагуванню елемента, до якого вони не мають доступу, АЛО що, якщо вони змінять ідентифікатор на елемент, до якого вони мають доступ?

Це не помилка дозволу, а помилка цілісності даних. Я хочу переконатися, що елемент, який вони отримали з GET для редагування елемента той самий, що і вони POST оновити його зміст.

Який правильний спосіб зробити це?

Відповіді:

1 для відповіді № 1

Якщо вони мають до нього доступ, вони в основному мають"зламати вашу програму", щоб зробити щось, що вони вже можуть зробити за допомогою графічного інтерфейсу (нібито ...). В основному це було б те саме, що спроба редагування цього іншого елемента. І якщо хтось модифікує вихідний код на стороні клієнта, дійсно можуть трапитися дивні речі.

Звичайно, повинен бути доступ на стороні сервераконтролю та перевірки, тому будь-які недійсні дані відхиляються. Але якщо все, що вони передають, є дійсним, чому б вони не могли цього зробити? Тут насправді мало що можна зробити. Запит є запитом - якщо він дійсний, він дійсний. Незалежно від того, звідки він надходить.

Що робити, якщо я створюю запит у такому програмному забезпеченні, як Fiddler? Тоді я можу змінювати свої дані, навіть не бачачи вашої веб-програми - взагалі не «редагуючи» щось.


0 для відповіді № 2

Можливо, я пізно відповісти на це питання, і я також стикаюся з тією ж проблемою, і я уникнув цієї проблеми наступним чином.

  1. Як ви вже сказали, у вас є ItemId і під час публікаціїхтось змінює ItemId на інше значення, щоб він міг переписати інший елемент, оскільки цей користувач має дозвіл також редагувати цей елемент. Щоб уникнути цієї проблеми, я думаю, що на основі ItemId генерують ідентифікатор, який є менш передбачуваним (як хеш-значення ідентифікатора елемента, і цей хеш базується на ключі, так що кожна сторінка вашої програми має інший ключ, так що якщо itemid однаковий, то він також генерує різне хеш-значення).

  2. Тепер, коли форма отримує допис.Спочатку отримуємо ItemId і отримуємо його хеш-значення на основі ключа та порівнюємо з тим, що було раніше створеним, і якщо порівняння не вдається, хтось загартує або ItemId, або хеш-значення, і ми в кінцевому підсумку просимо про помилку.

Ось невеликий приклад.

public static class HtmlHelperExtentions
{
public static MvcHtmlString GenerateIntegrityToken(this HtmlHelper htmlHelper,
string name , string valuefromwhichtokengenerate , string key)
{
var builder = new TagBuilder("input");
builder.MergeAttribute("type", "hidden");
builder.MergeAttribute("name", "DataIntegrity_" + name);
builder.MergeAttribute("value", DataIntegrityHelper.GetTokenValue(valuefromwhichtokengenerate,key));
return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
}
}

public static class DataIntegrityHelper
{
public static bool IsValid(string value,string encryptedvalue,string key)
{
string tempEncryptedValue = GetTokenValue(value, key);
return string.Equals(tempEncryptedValue,encryptedvalue,StringComparison.InvariantCultureIgnoreCase);
}

public static string GetTokenValue(string value, string key)
{
if (string.IsNullOrEmpty(key))
key = "MVCTokenForDataIntigrity4@5#6";
else
key = "1@2#3" + key;
byte[] keys = System.Text.UTF8Encoding.UTF8.GetBytes(key);
byte[] messageBytes = System.Text.UTF8Encoding.UTF8.GetBytes(value);
HMAC mac = HMACSHA256.Create();
mac.Key = keys;
byte[] hashBytes = mac.ComputeHash(messageBytes);
return ByteToString(hashBytes);
}

public static string ByteToString(byte[] buff)
{
string sbinary = "";

for (int i = 0; i < buff.Length; i++)
{
sbinary += buff[i].ToString("X2"); // hex format
}
return (sbinary);
}
}

Приклад особи Модель.

public class Person
{
public int Id { get; set; }
public string DataIntegrity_Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

На вигляд (person.cshtml)

@using (Html.BeginForm())
{
@Html.GenerateIntegrityToken("Id",Model.Id.ToString(),"Hello")
@Html.HiddenFor(cc=>cc.Id)
<br />
@Html.TextBoxFor(cc=>cc.FirstName)
<br />
@Html.TextBoxFor(cc => cc.LastName)
<br />
<input type="submit" />
}

Дії контролера

 public ActionResult Person()
{
return View(new Person());
}

[HttpPost]
public ActionResult Person(Person person)
{
if (Extentions.DataIntegrityHelper.IsValid(person.Id.ToString(), person.DataIntegrity_Id, "Hello"))
{
return View(person);
}
else
{
return Content("Data integrity validation fails.");
}
}