Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, ASP.NET Core web API'sinde JSON Düzeltme Eki isteklerinin nasıl işleneceğini açıklanmaktadır.
ASP.NET Core web API'de JSON Yaması desteği, System.Text.Json serileştirmesine dayanır ve Microsoft.AspNetCore.JsonPatch.SystemTextJson
NuGet paketini gerektirir.
JSON Patch standardı nedir?
JSON Patch standardı:
JSON belgesine uygulanacak değişiklikleri açıklamaya yönelik standart bir biçimdir.
RFC 6902'de tanımlanır ve JSON kaynaklarında kısmi güncelleştirmeler gerçekleştirmek için RESTful API'lerinde yaygın olarak kullanılır.
Aşağıdakiler gibi bir JSON belgesini değiştiren işlem dizisini açıklar:
add
remove
replace
move
copy
test
Web uygulamalarında JSON Patch genellikle bir kaynağın kısmi güncelleştirmelerini gerçekleştirmek için PATCH işleminde kullanılır. İstemciler, bir güncelleştirme için kaynağın tamamını göndermek yerine yalnızca değişiklikleri içeren bir JSON Düzeltme Eki belgesi gönderebilir. Yama yapmak, yük boyutunu azaltır ve verimliliği artırır.
JSON Düzeltme Eki standardına genel bakış için bkz. jsonpatch.com.
ASP.NET Core web API'de JSON Patch'in desteklenmesi
ASP.NET Core web API'sinde JSON Patch desteği, .NET 10'dan itibaren System.Text.Json serileştirmeye dayanır ve Microsoft.AspNetCore.JsonPatch serileştirme temelli System.Text.Json uygulamasıyla gerçekleştirilir. Bu özellik:
-
Microsoft.AspNetCore.JsonPatch.SystemTextJson
NuGet paketini gerektirir. - Modern .NET uygulamalarıyla uyumlu olan System.Text.Json kitaplığı, .NET için optimize edilmiştir.
- Eski
Newtonsoft.Json
tabanlı uygulamaya kıyasla daha iyi performans ve azaltılmış bellek kullanımı sağlar. EskiNewtonsoft.Json
tabanlı uygulama hakkında daha fazla bilgi için bu makalenin .NET 9 sürümüne bakın.
Uyarı
Microsoft.AspNetCore.JsonPatch serileştirmesine dayalı System.Text.Json uygulaması, eski Newtonsoft.Json
tabanlı uygulamanın doğrudan bir ikamesi değildir. Dinamik türleri desteklemez, örneğin ExpandoObject.
Önemli
JSON Patch standardının doğal güvenlik riskleri vardır. Bu riskler JSON Patch standardına bağlı olduğundan, ASP.NET Core uygulaması doğal güvenlik risklerini azaltmaya çalışmaz. JSON Patch belgesinin hedef nesneye uygulanmasının güvenli olduğundan emin olmak geliştiricinin sorumluluğundadır. Daha fazla bilgi için Güvenlik Risklerini Azaltma bölümüne bakın.
JSON Düzeltme Eki desteğini System.Text.Json ile etkinleştirin
JSON Yaması desteğini System.Text.Json etkinleştirmek için Microsoft.AspNetCore.JsonPatch.SystemTextJson
NuGet paketini yükleyin.
dotnet add package Microsoft.AspNetCore.JsonPatch.SystemTextJson --prerelease
Bu paket, JsonPatchDocument<TModel> sınıfını, T
türü nesneler için JSON Patch belgesini temsil etmek üzere ve System.Text.Json kullanılarak JSON Patch belgelerinin seri hale getirilmesi ve seri durumdan çıkarılması için özel mantığı sağlar.
JsonPatchDocument<TModel> sınıfının anahtar yöntemi, düzeltme eki işlemlerini ApplyTo(Object) türündeki bir hedef nesneye uygulayan T
yöntemidir.
JSON Patch uygulayan metot kodu
BIR API denetleyicisinde JSON Düzeltme Eki için bir eylem yöntemi:
- özniteliğiyle HttpPatchAttribute ek açıklama eklenir.
- genellikle ile bir JsonPatchDocument<TModel>FromBodyAttributekabul eder.
- Değişiklikleri uygulamak için düzeltme eki belgesine çağrılar ApplyTo(Object) .
Örnek Denetleyici Eylemi yöntemi:
[HttpPatch("{id}", Name = "UpdateCustomer")]
public IActionResult Update(AppDb db, string id, [FromBody] JsonPatchDocument<Customer> patchDoc)
{
// Retrieve the customer by ID
var customer = db.Customers.FirstOrDefault(c => c.Id == id);
// Return 404 Not Found if customer doesn't exist
if (customer == null)
{
return NotFound();
}
patchDoc.ApplyTo(customer, jsonPatchError =>
{
var key = jsonPatchError.AffectedObject.GetType().Name;
ModelState.AddModelError(key, jsonPatchError.ErrorMessage);
}
);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return new ObjectResult(customer);
}
Örnek uygulamadaki bu kod aşağıdakilerle Customer
ve Order
modelleriyle çalışır:
namespace App.Models;
public class Customer
{
public string Id { get; set; }
public string? Name { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
public string? Address { get; set; }
public List<Order>? Orders { get; set; }
public Customer()
{
Id = Guid.NewGuid().ToString();
}
}
namespace App.Models;
public class Order
{
public string Id { get; set; }
public DateTime? OrderDate { get; set; }
public DateTime? ShipDate { get; set; }
public decimal TotalAmount { get; set; }
public Order()
{
Id = Guid.NewGuid().ToString();
}
}
Örnek eylem yönteminin temel adımları:
-
Müşteriyi Alma:
- yöntemi, sağlanan kimliği kullanarak veritabanından
Customer
birAppDb
nesne alır. - Hiçbir
Customer
nesne bulunmazsa, bir404 Not Found
yanıt döndürür.
- yöntemi, sağlanan kimliği kullanarak veritabanından
-
JSON Düzeltme Eki Uygula:
-
ApplyTo(Object) yöntemi, patchDoc'tan JSON Patch işlemlerini alınan
Customer
nesneye uygular. - Düzeltme eki uygulaması sırasında geçersiz işlemler veya çakışmalar gibi hatalar oluşursa, bunlar bir hata işleme temsilcisi tarafından yakalanır. Bu temsilci, etkilenen nesnenin tür adını ve hata iletisini kullanarak
ModelState
öğesine hata iletileri ekler.
-
ApplyTo(Object) yöntemi, patchDoc'tan JSON Patch işlemlerini alınan
-
ModelState Doğrulama:
- Düzeltme eki uygulandıktan sonra, yöntem
ModelState
üzerindeki hataları kontrol eder. -
ModelState
geçersizse, örneğin düzeltme eki hatalarından dolayı, doğrulama hatalarını içeren bir400 Bad Request
yanıt döndürür.
- Düzeltme eki uygulandıktan sonra, yöntem
-
Güncelleştirilmiş Müşteriyi İade Edin:
- Düzeltme eki başarıyla uygulanırsa ve
ModelState
geçerliyse, yöntem yanıttaki güncelleştirilmişCustomer
nesneyi döndürür.
- Düzeltme eki başarıyla uygulanırsa ve
Örnek hata yanıtı:
Belirtilen yol geçersiz olduğunda bir JSON Patch işlemi için 400 Bad Request
yanıtının gövdesini aşağıdaki örnek gösterir.
{
"Customer": [
"The target location specified by path segment 'foobar' was not found."
]
}
Nesneye JSON Düzeltme Eki belgesi uygulama
Aşağıdaki örnekler, JSON Patch belgesini bir nesneye uygulamak için ApplyTo(Object) yönteminin nasıl kullanılacağını göstermektedir.
Örnek: Bir JsonPatchDocument<TModel> nesneye uygulayın
Aşağıdaki örnekte gösterilmiştir:
-
add
,replace
veremove
işlemleri. - İç içe geçmiş özelliklerde işlemler.
- Diziye yeni öğe ekleme.
- JSON yama belgesinde JSON Dize Enum Dönüştürücüsü kullanma.
// Original object
var person = new Person {
FirstName = "John",
LastName = "Doe",
Email = "johndoe@gmail.com",
PhoneNumbers = [new() {Number = "123-456-7890", Type = PhoneNumberType.Mobile}],
Address = new Address
{
Street = "123 Main St",
City = "Anytown",
State = "TX"
}
};
// Raw JSON patch document
string jsonPatch = """
[
{ "op": "replace", "path": "/FirstName", "value": "Jane" },
{ "op": "remove", "path": "/Email"},
{ "op": "add", "path": "/Address/ZipCode", "value": "90210" },
{ "op": "add", "path": "/PhoneNumbers/-", "value": { "Number": "987-654-3210",
"Type": "Work" } }
]
""";
// Deserialize the JSON patch document
var patchDoc = JsonSerializer.Deserialize<JsonPatchDocument<Person>>(jsonPatch);
// Apply the JSON patch document
patchDoc!.ApplyTo(person);
// Output updated object
Console.WriteLine(JsonSerializer.Serialize(person, serializerOptions));
Önceki örnekte güncelleştirilmiş nesnenin aşağıdaki çıkışı elde edilir:
{
"firstName": "Jane",
"lastName": "Doe",
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "TX",
"zipCode": "90210"
},
"phoneNumbers": [
{
"number": "123-456-7890",
"type": "Mobile"
},
{
"number": "987-654-3210",
"type": "Work"
}
]
}
ApplyTo(Object) yöntemi, işleme System.Text.Json kurallarını ve seçeneklerini, aşağıdaki seçenekler tarafından denetlenen davranış da dahil olmak üzere, JsonPatchDocument<TModel> için geçerli olan kurallar ve seçenekleri izler.
- JsonNumberHandling: Sayısal özelliklerin dizelerden okunup okunmadığı.
- PropertyNameCaseInsensitive: Özellik adlarının büyük/küçük harfe duyarlı olup olmadığı.
System.Text.Json ve yeni JsonPatchDocument<TModel> uygulaması arasındaki ana farklar:
- Hedef nesnenin bildirilmiş türü değil, çalışma zamanındaki türü, hangi özellikleri ApplyTo(Object) yamanacağını belirler.
- System.Text.Json seri durumdan çıkarma, uygun özellikleri tanımlamak için bildirilen türe dayanır.
Örnek: Hata işleme ile JsonPatchDocument'i uygulama
JSON Düzeltme Eki belgesi uygulanırken oluşabilecek çeşitli hatalar vardır. Örneğin, hedef nesne belirtilen özelliğe sahip olmayabilir veya belirtilen değer özellik türüyle uyumsuz olabilir.
JSON Patch
, belirtilen bir değerin test
hedef özelliğe eşit olup olmadığını denetleyen işlemi destekler. Aksi takdirde bir hata döndürür.
Aşağıdaki örnekte bu hataların düzgün bir şekilde nasıl işleneceğini gösterilmektedir.
Önemli
ApplyTo(Object) yöntemine aktarılan nesne doğrudan değiştirilir. İşlemlerden herhangi biri başarısız olursa, değişiklikleri atmak çağırıcının sorumluluğundadır.
// Original object
var person = new Person {
FirstName = "John",
LastName = "Doe",
Email = "johndoe@gmail.com"
};
// Raw JSON patch document
string jsonPatch = """
[
{ "op": "replace", "path": "/Email", "value": "janedoe@gmail.com"},
{ "op": "test", "path": "/FirstName", "value": "Jane" },
{ "op": "replace", "path": "/LastName", "value": "Smith" }
]
""";
// Deserialize the JSON patch document
var patchDoc = JsonSerializer.Deserialize<JsonPatchDocument<Person>>(jsonPatch);
// Apply the JSON patch document, catching any errors
Dictionary<string, string[]>? errors = null;
patchDoc!.ApplyTo(person, jsonPatchError =>
{
errors ??= new ();
var key = jsonPatchError.AffectedObject.GetType().Name;
if (!errors.ContainsKey(key))
{
errors.Add(key, new string[] { });
}
errors[key] = errors[key].Append(jsonPatchError.ErrorMessage).ToArray();
});
if (errors != null)
{
// Print the errors
foreach (var error in errors)
{
Console.WriteLine($"Error in {error.Key}: {string.Join(", ", error.Value)}");
}
}
// Output updated object
Console.WriteLine(JsonSerializer.Serialize(person, serializerOptions));
Önceki örnekte aşağıdaki çıkış elde edilir:
Error in Person: The current value 'John' at path 'FirstName' is not equal
to the test value 'Jane'.
{
"firstName": "John",
"lastName": "Smith", <<< Modified!
"email": "janedoe@gmail.com", <<< Modified!
"phoneNumbers": []
}
Güvenlik risklerini azaltma
Paketi kullanırken Microsoft.AspNetCore.JsonPatch.SystemTextJson
olası güvenlik risklerini anlamak ve azaltmak kritik önem taşır. Aşağıdaki bölümlerde JSON Düzeltme Eki ile ilişkili tanımlanan güvenlik riskleri özetlenmiştir ve paketin güvenli kullanımını sağlamak için önerilen risk azaltmaları sağlanır.
Önemli
Bu, kapsamlı bir tehdit listesi değildir. Uygulama geliştiricileri, uygulamaya özgü kapsamlı bir liste belirlemek ve gerektiğinde uygun risk azaltmaları bulmak için kendi tehdit modeli incelemelerini yapmalıdır. Örneğin, koleksiyonları düzeltme eki işlemlerine sunan uygulamalar, bu işlemlerin koleksiyonun başına öğe eklemesi veya kaldırması durumunda algoritmasal karmaşıklık saldırıları olasılığını göz önünde bulundurmalıdır.
JSON Patch işlevselliğini uygulamalarıyla tümleştirirken güvenlik risklerini en aza indirmek için geliştiriciler şunları yapmalıdır:
- Kendi uygulamaları için kapsamlı tehdit modelleri çalıştırın.
- Tanımlanan tehditleri ele alın.
- Aşağıdaki bölümlerde önerilen azaltmaları izleyin.
Bellek amplifikasyonu yoluyla Hizmet Reddi (DoS)
-
Senaryo: Kötü amaçlı istemci, büyük nesne grafiklerini birden çok kez çoğaltan ve aşırı bellek tüketimine yol açan bir
copy
işlem gönderir. - Etki: Hizmet kesintilerine neden olan olası Out-Of-Memory (OOM) koşulları.
-
Hafifletme:
- ** ApplyTo(Object) çağırmadan önce gelen JSON Patch belgelerini boyut ve yapı açısından doğrulayın.
- Doğrulamanın uygulamaya özgü olması gerekir, ancak örnek bir doğrulama aşağıdakine benzer olabilir:
public void Validate(JsonPatchDocument<T> patch)
{
// This is just an example. It's up to the developer to make sure that
// this case is handled properly, based on the app needs.
if (patch.Operations.Where(op=>op.OperationType == OperationType.Copy).Count()
> MaxCopyOperationsCount)
{
throw new InvalidOperationException();
}
}
İş Mantığı Bozulması
- Senaryo: Yama işlemleri, iş kısıtlamalarını ihlal ederek alanları örtük sabit değerlerle (örneğin, iç bayraklar, kimlikler veya hesaplanan alanlar) işleyebilir.
- Etki: Veri bütünlüğü sorunları ve istenmeyen uygulama davranışı.
-
Hafifletme:
- Değiştirilmesi güvenli olan açıkça tanımlanmış özelliklerle POCO'ları (Düz Eski CLR Nesneleri) kullanın.
- Hedef nesnede hassas veya güvenlik açısından kritik özellikleri ortaya çıkarmaktan kaçının.
- POCO nesnesi kullanılmıyorsa, işlemleri uyguladıktan sonra yaması yapılmış nesneyi doğrulayarak iş kurallarının ve değişmezlerin ihlal edilmediğinden emin olun.
- Değiştirilmesi güvenli olan açıkça tanımlanmış özelliklerle POCO'ları (Düz Eski CLR Nesneleri) kullanın.
Kimlik doğrulaması ve yetkilendirme
- Senaryo: Kimliği doğrulanmamış veya yetkisiz istemciler kötü amaçlı JSON Düzeltme Eki istekleri gönderir.
- Etki: Hassas verileri değiştirmek veya uygulama davranışını kesintiye uğratmak için yetkisiz erişim.
-
Hafifletme:
- Uygun kimlik doğrulama ve yetkilendirme mekanizmalarıyla JSON Düzeltme Eki isteklerini kabul eden uç noktaları koruyun.
- Erişimi güvenilen istemcilere veya uygun izinlere sahip kullanıcılara kısıtlayın.
Kodu alma
Örnek kodu görüntüleyin veya indirme. (Nasıl indirilir).
Örneği test etmek için uygulamayı çalıştırın ve aşağıdaki ayarlarla HTTP istekleri gönderin:
- URL:
http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
- HTTP yöntemi:
PATCH
- Üstbilgi:
Content-Type: application/json-patch+json
- Gövde: JSON proje klasöründeki JSON düzeltme eki belge örneklerinden birini kopyalayıp yapıştırın.
Ek kaynaklar
Bu makalede, ASP.NET Core web API'sinde JSON Düzeltme Eki isteklerinin nasıl işleneceğini açıklanmaktadır.
Önemli
JSON Patch standardının doğal güvenlik riskleri vardır. Bu uygulama , bu doğal güvenlik risklerini azaltmaya çalışmaz. JSON Patch belgesinin hedef nesneye uygulanmasının güvenli olduğundan emin olmak geliştiricinin sorumluluğundadır. Daha fazla bilgi için Güvenlik Risklerini Azaltma bölümüne bakın.
Paket yükleme
ASP.NET Core web API'sindeki JSON Düzeltme Eki desteği NuGet paketini temel alır Newtonsoft.Json
ve gerektirir Microsoft.AspNetCore.Mvc.NewtonsoftJson
.
JSON Düzeltme Eki desteğini etkinleştirmek için:
Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet paketini yükleyin.AddNewtonsoftJson çağrısı yapın. Örneğin:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .AddNewtonsoftJson(); var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
AddNewtonsoftJson
, tümSystem.Text.Json
için kullanılan varsayılan tabanlı giriş ve çıkış biçimlendiricilerinin yerini alır. Bu uzantı yöntemi aşağıdaki MVC hizmet kayıt yöntemleriyle uyumludur:
JsonPatch için üst bilginin Content-Type
olarak ayarlanması application/json-patch+json
gerekir.
System.Text.Json kullanırken JSON Düzeltme Eki desteği ekleme
System.Text.Json
Tabanlı giriş biçimlendirici JSON Düzeltme Eki'ni desteklemez. kullanarak Newtonsoft.Json
JSON Düzeltme Eki desteği eklemek ve diğer giriş ve çıkış biçimlendiricilerini değiştirmeden bırakmak için:
Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet paketini yükleyin.Güncelleştirme
Program.cs
:using JsonPatchSample; using Microsoft.AspNetCore.Mvc.Formatters; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(options => { options.InputFormatters.Insert(0, MyJPIF.GetJsonPatchInputFormatter()); }); var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Extensions.Options; namespace JsonPatchSample; public static class MyJPIF { public static NewtonsoftJsonPatchInputFormatter GetJsonPatchInputFormatter() { var builder = new ServiceCollection() .AddLogging() .AddMvc() .AddNewtonsoftJson() .Services.BuildServiceProvider(); return builder .GetRequiredService<IOptions<MvcOptions>>() .Value .InputFormatters .OfType<NewtonsoftJsonPatchInputFormatter>() .First(); } }
Yukarıdaki kod bir örneği NewtonsoftJsonPatchInputFormatter oluşturur ve bunu koleksiyondaki MvcOptions.InputFormatters ilk girdi olarak ekler. Bu kayıt sırası aşağıdakilerin sağlanmasını sağlar:
-
NewtonsoftJsonPatchInputFormatter
JSON Düzeltme Eki isteklerini işler. - Mevcut
System.Text.Json
tabanlı giriş ve biçimlendiriciler diğer tüm JSON isteklerini ve yanıtlarını işler.
Newtonsoft.Json.JsonConvert.SerializeObject
bir serileştirmek JsonPatchDocumentiçin yöntemini kullanın.
PATCH HTTP istek yöntemi
PUT ve PATCH yöntemleri, mevcut bir kaynağı güncelleştirmek için kullanılır. Aralarındaki fark, PUT'nin kaynağın tamamının yerini aldığı, PATCH'nin ise yalnızca değişiklikleri belirttiğidir.
JSON Düzeltme Eki
JSON Düzeltme Eki , bir kaynağa uygulanacak güncelleştirmeleri belirtme biçimidir. JSON Patch belgesinde bir dizi işlem vardır. Her işlem belirli bir değişiklik türünü tanımlar. Dizi öğesi ekleme veya özellik değerini değiştirme gibi değişikliklere örnek olarak verilebilir.
Örneğin, aşağıdaki JSON belgeleri bir kaynağı, kaynak için JSON Patch belgesini ve Patch işlemlerinin uygulanmasının sonucunu temsil eder.
Kaynak örneği
{
"customerName": "John",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
}
]
}
JSON düzeltme eki örneği
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
Yukarıdaki JSON kodunda:
-
op
özelliği, işlemin türünü gösterir. -
path
özelliği, güncelleştirilecek öğeyi gösterir. -
value
özelliği yeni değeri sağlar.
Düzeltme eki sonrasındaki kaynak
Yukarıdaki JSON Düzeltme Eki belgesini uyguladıktan sonraki kaynak aşağıdadır:
{
"customerName": "Barry",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
},
{
"orderName": "Order2",
"orderType": null
}
]
}
Bir kaynağa JSON Düzeltme Eki belgesi uygulanarak yapılan değişiklikler atomik değerdir. Listedeki herhangi bir işlem başarısız olursa, listedeki hiçbir işlem uygulanmaz.
Yol söz dizimi
İşlem nesnesinin path özelliği düzeyler arasında eğik çizgi içerir. Örneğin, "/address/zipCode"
.
Dizi öğelerini belirtmek için sıfır tabanlı dizinler kullanılır. Dizinin ilk öğesi addresses
konumunda /addresses/0
olacaktır. Dizinin add
sonuna kadar dizin numarası yerine kısa çizgi (-
) kullanın: /addresses/-
.
Operasyonlar
Aşağıdaki tabloda JSON Düzeltme Eki belirtiminde tanımlandığı gibi desteklenen işlemler gösterilmektedir:
İşlem | Notlar |
---|---|
add |
Özellik veya dizi öğesi ekleyin. Mevcut özellik için: set value. |
remove |
Bir özelliği veya dizi öğesini kaldırın. |
replace |
Aynı konumda ve ardından remove aynı konumda olduğu gibiadd . |
move |
Kaynaktan alınan değeri kullanarak kaynaktan remove hedefe kadar add olan değerle aynıdır. |
copy |
add Kaynaktan değer kullanan hedefle aynıdır. |
test |
= değeri sağlandıysa path value başarı durum kodunu döndürür. |
ASP.NET Core'da JSON Düzeltme Eki
JSON Patch'in ASP.NET Core uygulaması Microsoft.AspNetCore.JsonPatch NuGet paketinde sağlanır.
Eylem yöntemi kodu
BIR API denetleyicisinde JSON Düzeltme Eki için bir eylem yöntemi:
- özniteliğiyle
HttpPatch
ek açıklama eklenir. - genellikle ile bir JsonPatchDocument<TModel>
[FromBody]
kabul eder. - Değişiklikleri uygulamak için düzeltme eki belgesine çağrılar ApplyTo(Object) .
Bir örnek aşağıda verilmiştir:
[HttpPatch]
public IActionResult JsonPatchWithModelState(
[FromBody] JsonPatchDocument<Customer> patchDoc)
{
if (patchDoc != null)
{
var customer = CreateCustomer();
patchDoc.ApplyTo(customer, ModelState);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return new ObjectResult(customer);
}
else
{
return BadRequest(ModelState);
}
}
Örnek uygulamadaki bu kod aşağıdaki Customer
modelle çalışır:
namespace JsonPatchSample.Models;
public class Customer
{
public string? CustomerName { get; set; }
public List<Order>? Orders { get; set; }
}
namespace JsonPatchSample.Models;
public class Order
{
public string OrderName { get; set; }
public string OrderType { get; set; }
}
Örnek eylem yöntemi:
- bir
Customer
oluşturur. - Düzeltme ekini uygular.
- Yanıtın gövdesindeki sonucu döndürür.
Gerçek bir uygulamada kod, verileri veritabanı gibi bir depodan alır ve düzeltme ekini uyguladıktan sonra veritabanını güncelleştirir.
Model durumu
Yukarıdaki eylem yöntemi örneği, model durumunu parametrelerinden biri olarak alan bir aşırı yüklemesini ApplyTo
çağırır. Bu seçenekle yanıtlarda hata iletileri alabilirsiniz. Aşağıdaki örnek, bir işlem için test
400 Hatalı İstek yanıtının gövdesini gösterir:
{
"Customer": [
"The current value 'John' at path 'customerName' != test value 'Nancy'."
]
}
Dinamik nesneler
Aşağıdaki eylem yöntemi örneği, bir dinamik nesneye düzeltme ekinin nasıl uygulanacağını gösterir:
[HttpPatch]
public IActionResult JsonPatchForDynamic([FromBody]JsonPatchDocument patch)
{
dynamic obj = new ExpandoObject();
patch.ApplyTo(obj);
return Ok(obj);
}
Ekleme işlemi
- Bir dizi öğesine işaret ederse
path
: tarafındanpath
belirtilen öğeden önce yeni öğe ekler. - Bir özelliğe işaret ederse
path
: özellik değerini ayarlar. - Var olmayan bir konuma işaret ederse
path
:- Düzeltme eki uygulama kaynağı dinamik bir nesneyse: bir özellik ekler.
- Düzeltme eki uygulanacak kaynak statik bir nesneyse, istek başarısız olur.
Aşağıdaki örnek düzeltme eki belgesi değerini CustomerName
ayarlar ve dizinin sonuna Order
bir Orders
nesne ekler.
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
Kaldırma işlemi
- Bir dizi öğesine işaret ederse
path
: öğesini kaldırır. - Bir özelliğe işaret ederse
path
:- Düzeltme eki uygulanacak kaynak dinamik bir nesneyse: özelliği kaldırır.
- Düzeltme eki uygulanacak kaynak statik bir nesneyse:
- Özellik null atanabilirse: null olarak ayarlar.
- Özelliği null atanamazsa olarak ayarlar
default<T>
.
Aşağıdaki örnek düzeltme eki belge null olarak ayarlanır CustomerName
ve silinir Orders[0]
:
[
{
"op": "remove",
"path": "/customerName"
},
{
"op": "remove",
"path": "/orders/0"
}
]
Değiştirme işlemi
Bu işlem işlevsel olarak bir remove
ile aynıdır ve ardından bir ile aynıdır add
.
Aşağıdaki örnek düzeltme eki belgesi değerini CustomerName
ayarlar ve değerini yeni Orders[0]
bir nesneyle değiştirirOrder
:
[
{
"op": "replace",
"path": "/customerName",
"value": "Barry"
},
{
"op": "replace",
"path": "/orders/0",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
Taşıma işlemi
- Bir dizi öğesine işaret ederse
path
: öğeyi öğenin konumunafrom
kopyalarpath
, ardından öğesinderemove
birfrom
işlem çalıştırır. - Bir özelliğe işaret ederse
path
: özelliğinfrom
path
değerini özelliğe kopyalar, ardından özelliğinderemove
birfrom
işlem çalıştırır. - Var olmayan bir özelliğe işaret ederse
path
:- Düzeltme eki uygulanacak kaynak statik bir nesneyse, istek başarısız olur.
- Düzeltme eki uygulanacak kaynak dinamik bir nesneyse: özelliği tarafından
from
belirtilen konuma kopyalarpath
ve özelliği üzerinderemove
birfrom
işlem çalıştırır.
Aşağıdaki örnek düzeltme eki belgesi:
- değerini
Orders[0].OrderName
olarakCustomerName
kopyalar. - Null olarak ayarlanır
Orders[0].OrderName
. - öncesine
Orders[1]
giderOrders[0]
.
[
{
"op": "move",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "move",
"from": "/orders/1",
"path": "/orders/0"
}
]
Kopyalama işlemi
Bu işlem işlevsel olarak son move
adım olmadan bir remove
işlemle aynıdır.
Aşağıdaki örnek düzeltme eki belgesi:
- değerini
Orders[0].OrderName
olarakCustomerName
kopyalar. - öncesinin
Orders[1]
Orders[0]
bir kopyasını ekler.
[
{
"op": "copy",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "copy",
"from": "/orders/1",
"path": "/orders/0"
}
]
Test işlemi
tarafından path
belirtilen konumdaki değer, içinde value
sağlanan değerden farklıysa istek başarısız olur. Bu durumda düzeltme eki belgesindeki diğer tüm işlemler başarılı olsa bile PATCH isteğinin tamamı başarısız olur.
İşlem test
genellikle eşzamanlılık çakışması olduğunda güncelleştirme yapılmasını önlemek için kullanılır.
Aşağıdaki örnek düzeltme eki belgesinin ilk değeri CustomerName
"John" ise hiçbir etkisi yoktur, çünkü test başarısız olur:
[
{
"op": "test",
"path": "/customerName",
"value": "Nancy"
},
{
"op": "add",
"path": "/customerName",
"value": "Barry"
}
]
Kodu alma
Örnek kodu görüntüleyin veya indirme. (Nasıl indirilir).
Örneği test etmek için uygulamayı çalıştırın ve aşağıdaki ayarlarla HTTP istekleri gönderin:
- URL:
http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
- HTTP yöntemi:
PATCH
- Üstbilgi:
Content-Type: application/json-patch+json
- Gövde: JSON proje klasöründeki JSON düzeltme eki belge örneklerinden birini kopyalayıp yapıştırın.
Güvenlik risklerini azaltma
Microsoft.AspNetCore.JsonPatch
paketini Newtonsoft.Json
tabanlı uygulamayla kullanırken olası güvenlik risklerini anlamak ve azaltmak kritik önem taşır. Aşağıdaki bölümlerde JSON Düzeltme Eki ile ilişkili tanımlanan güvenlik riskleri özetlenmiştir ve paketin güvenli kullanımını sağlamak için önerilen risk azaltmaları sağlanır.
Önemli
Bu, kapsamlı bir tehdit listesi değildir. Uygulama geliştiricileri, uygulamaya özgü kapsamlı bir liste belirlemek ve gerektiğinde uygun risk azaltmaları bulmak için kendi tehdit modeli incelemelerini yapmalıdır. Örneğin, koleksiyonları düzeltme eki işlemlerine sunan uygulamalar, bu işlemlerin koleksiyonun başına öğe eklemesi veya kaldırması durumunda algoritmasal karmaşıklık saldırıları olasılığını göz önünde bulundurmalıdır.
Bu paketlerin tüketicileri, kendi uygulamaları için kapsamlı tehdit modelleri çalıştırarak ve tanımlanan tehditleri ele alırken aşağıdaki önerilen azaltmaları izleyerek, güvenlik risklerini en aza indirirken JSON Patch işlevselliğini uygulamalarıyla tümleştirebilir.
Bellek amplifikasyonu yoluyla Hizmet Reddi (DoS)
-
Senaryo: Kötü amaçlı istemci, büyük nesne grafiklerini birden çok kez çoğaltan ve aşırı bellek tüketimine yol açan bir
copy
işlem gönderir. - Etki: Hizmet kesintilerine neden olan olası Out-Of-Memory (OOM) koşulları.
-
Hafifletme:
- **
ApplyTo
çağırmadan önce gelen JSON Patch belgelerini boyut ve yapı açısından doğrulayın. - Doğrulamanın uygulamaya özgü olması gerekir, ancak örnek bir doğrulama aşağıdakine benzer olabilir:
- **
public void Validate(JsonPatchDocument patch)
{
// This is just an example. It's up to the developer to make sure that
// this case is handled properly, based on the app needs.
if (patch.Operations.Where(op => op.OperationType == OperationType.Copy).Count()
> MaxCopyOperationsCount)
{
throw new InvalidOperationException();
}
}
İş Mantığı Bozulması
- Senaryo: Yama işlemleri, iş kısıtlamalarını ihlal ederek alanları örtük sabit değerlerle (örneğin, iç bayraklar, kimlikler veya hesaplanan alanlar) işleyebilir.
- Etki: Veri bütünlüğü sorunları ve istenmeyen uygulama davranışı.
-
Hafifletme:
- Değiştirilmesi güvenli olan açıkça tanımlanmış özelliklere sahip POCO nesnelerini kullanın.
- Hedef nesnede hassas veya güvenlik açısından kritik özellikleri ortaya çıkarmaktan kaçının.
- PoCO nesnesi kullanılmazsa, iş kurallarının ve sabitlerin ihlal edilmediğinden emin olmak için işlemler uygulandıktan sonra değişiklik yapılan nesneyi doğrulayın.
Kimlik doğrulaması ve yetkilendirme
- Senaryo: Kimliği doğrulanmamış veya yetkisiz istemciler kötü amaçlı JSON Düzeltme Eki istekleri gönderir.
- Etki: Hassas verileri değiştirmek veya uygulama davranışını kesintiye uğratmak için yetkisiz erişim.
-
Hafifletme:
- Uygun kimlik doğrulama ve yetkilendirme mekanizmalarıyla JSON Düzeltme Eki isteklerini kabul eden uç noktaları koruyun.
- Erişimi güvenilen istemcilere veya uygun izinlere sahip kullanıcılara kısıtlayın.
Ek kaynaklar
Bu makalede, ASP.NET Core web API'sinde JSON Düzeltme Eki isteklerinin nasıl işleneceğini açıklanmaktadır.
Önemli
JSON Patch standardının doğal güvenlik riskleri vardır. Bu riskler JSON Düzeltme Eki standardına bağlı olduğundan, bu uygulama doğal güvenlik risklerini azaltmaya çalışmaz. JSON Patch belgesinin hedef nesneye uygulanmasının güvenli olduğundan emin olmak geliştiricinin sorumluluğundadır. Daha fazla bilgi için Güvenlik Risklerini Azaltma bölümüne bakın.
Paket yükleme
Uygulamanızda JSON Düzeltme Eki desteğini etkinleştirmek için aşağıdaki adımları tamamlayın:
Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet paketini yükleyin.projenin
Startup.ConfigureServices
yöntemini çağıracak AddNewtonsoftJsonşekilde güncelleştirin. Örneğin:services .AddControllersWithViews() .AddNewtonsoftJson();
AddNewtonsoftJson
MVC hizmet kayıt yöntemleriyle uyumludur:
JSON Patch, AddNewtonsoftJson ve System.Text.Json
AddNewtonsoftJson
System.Text.Json
, tüm JSON içeriğini biçimlendirmek için kullanılan tabanlı giriş ve çıkış biçimlendiricilerinin yerini alır. kullanarak Newtonsoft.Json
JSON Düzeltme Eki desteği eklemek ve diğer biçimlendiricileri değiştirmeden bırakmak için projenin Startup.ConfigureServices
yöntemini aşağıdaki gibi güncelleştirin:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options =>
{
options.InputFormatters.Insert(0, GetJsonPatchInputFormatter());
});
}
private static NewtonsoftJsonPatchInputFormatter GetJsonPatchInputFormatter()
{
var builder = new ServiceCollection()
.AddLogging()
.AddMvc()
.AddNewtonsoftJson()
.Services.BuildServiceProvider();
return builder
.GetRequiredService<IOptions<MvcOptions>>()
.Value
.InputFormatters
.OfType<NewtonsoftJsonPatchInputFormatter>()
.First();
}
Yukarıdaki kod için paket ve aşağıdaki Microsoft.AspNetCore.Mvc.NewtonsoftJson
deyimler gerekirusing
:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Linq;
Newtonsoft.Json.JsonConvert.SerializeObject
JsonPatchDocument'ı seri hale getirmek için yöntemini kullanın.
PATCH HTTP istek yöntemi
PUT ve PATCH yöntemleri, mevcut bir kaynağı güncelleştirmek için kullanılır. Aralarındaki fark, PUT'nin kaynağın tamamının yerini aldığı, PATCH'nin ise yalnızca değişiklikleri belirttiğidir.
JSON Düzeltme Eki
JSON Düzeltme Eki , bir kaynağa uygulanacak güncelleştirmeleri belirtme biçimidir. JSON Patch belgesinde bir dizi işlem vardır. Her işlem belirli bir değişiklik türünü tanımlar. Dizi öğesi ekleme veya özellik değerini değiştirme gibi değişikliklere örnek olarak verilebilir.
Örneğin, aşağıdaki JSON belgeleri bir kaynağı, kaynak için JSON Patch belgesini ve Patch işlemlerinin uygulanmasının sonucunu temsil eder.
Kaynak örneği
{
"customerName": "John",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
}
]
}
JSON düzeltme eki örneği
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
Yukarıdaki JSON kodunda:
-
op
özelliği, işlemin türünü gösterir. -
path
özelliği, güncelleştirilecek öğeyi gösterir. -
value
özelliği yeni değeri sağlar.
Düzeltme eki sonrasındaki kaynak
Yukarıdaki JSON Düzeltme Eki belgesini uyguladıktan sonraki kaynak aşağıdadır:
{
"customerName": "Barry",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
},
{
"orderName": "Order2",
"orderType": null
}
]
}
Bir kaynağa JSON Düzeltme Eki belgesi uygulanarak yapılan değişiklikler atomik değerdir. Listedeki herhangi bir işlem başarısız olursa, listedeki hiçbir işlem uygulanmaz.
Yol söz dizimi
İşlem nesnesinin path özelliği düzeyler arasında eğik çizgi içerir. Örneğin, "/address/zipCode"
.
Dizi öğelerini belirtmek için sıfır tabanlı dizinler kullanılır. Dizinin ilk öğesi addresses
konumunda /addresses/0
olacaktır. Dizinin add
sonuna kadar dizin numarası yerine kısa çizgi (-
) kullanın: /addresses/-
.
Operasyonlar
Aşağıdaki tabloda JSON Düzeltme Eki belirtiminde tanımlandığı gibi desteklenen işlemler gösterilmektedir:
İşlem | Notlar |
---|---|
add |
Özellik veya dizi öğesi ekleyin. Mevcut özellik için: set value. |
remove |
Bir özelliği veya dizi öğesini kaldırın. |
replace |
Aynı konumda ve ardından remove aynı konumda olduğu gibiadd . |
move |
Kaynaktan alınan değeri kullanarak kaynaktan remove hedefe kadar add olan değerle aynıdır. |
copy |
add Kaynaktan değer kullanan hedefle aynıdır. |
test |
= değeri sağlandıysa path value başarı durum kodunu döndürür. |
ASP.NET Core'da JSON Düzeltme Eki
JSON Patch'in ASP.NET Core uygulaması Microsoft.AspNetCore.JsonPatch NuGet paketinde sağlanır.
Eylem yöntemi kodu
BIR API denetleyicisinde JSON Düzeltme Eki için bir eylem yöntemi:
- özniteliğiyle
HttpPatch
ek açıklama eklenir. - genellikle ile bir
JsonPatchDocument<T>
[FromBody]
kabul eder. - Değişiklikleri uygulamak için düzeltme eki belgesine çağrılar
ApplyTo
.
Bir örnek aşağıda verilmiştir:
[HttpPatch]
public IActionResult JsonPatchWithModelState(
[FromBody] JsonPatchDocument<Customer> patchDoc)
{
if (patchDoc != null)
{
var customer = CreateCustomer();
patchDoc.ApplyTo(customer, ModelState);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return new ObjectResult(customer);
}
else
{
return BadRequest(ModelState);
}
}
Örnek uygulamadaki bu kod aşağıdaki Customer
modelle çalışır:
using System.Collections.Generic;
namespace JsonPatchSample.Models
{
public class Customer
{
public string CustomerName { get; set; }
public List<Order> Orders { get; set; }
}
}
namespace JsonPatchSample.Models
{
public class Order
{
public string OrderName { get; set; }
public string OrderType { get; set; }
}
}
Örnek eylem yöntemi:
- bir
Customer
oluşturur. - Düzeltme ekini uygular.
- Yanıtın gövdesindeki sonucu döndürür.
Gerçek bir uygulamada kod, verileri veritabanı gibi bir depodan alır ve düzeltme ekini uyguladıktan sonra veritabanını güncelleştirir.
Model durumu
Yukarıdaki eylem yöntemi örneği, model durumunu parametrelerinden biri olarak alan bir aşırı yüklemesini ApplyTo
çağırır. Bu seçenekle yanıtlarda hata iletileri alabilirsiniz. Aşağıdaki örnek, bir işlem için test
400 Hatalı İstek yanıtının gövdesini gösterir:
{
"Customer": [
"The current value 'John' at path 'customerName' is not equal to the test value 'Nancy'."
]
}
Dinamik nesneler
Aşağıdaki eylem yöntemi örneği, bir dinamik nesneye düzeltme ekinin nasıl uygulanacağını gösterir:
[HttpPatch]
public IActionResult JsonPatchForDynamic([FromBody]JsonPatchDocument patch)
{
dynamic obj = new ExpandoObject();
patch.ApplyTo(obj);
return Ok(obj);
}
Ekleme işlemi
- Bir dizi öğesine işaret ederse
path
: tarafındanpath
belirtilen öğeden önce yeni öğe ekler. - Bir özelliğe işaret ederse
path
: özellik değerini ayarlar. - Var olmayan bir konuma işaret ederse
path
:- Düzeltme eki uygulama kaynağı dinamik bir nesneyse: bir özellik ekler.
- Düzeltme eki uygulanacak kaynak statik bir nesneyse, istek başarısız olur.
Aşağıdaki örnek düzeltme eki belgesi değerini CustomerName
ayarlar ve dizinin sonuna Order
bir Orders
nesne ekler.
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
Kaldırma işlemi
- Bir dizi öğesine işaret ederse
path
: öğesini kaldırır. - Bir özelliğe işaret ederse
path
:- Düzeltme eki uygulanacak kaynak dinamik bir nesneyse: özelliği kaldırır.
- Düzeltme eki uygulanacak kaynak statik bir nesneyse:
- Özellik null atanabilirse: null olarak ayarlar.
- Özelliği null atanamazsa olarak ayarlar
default<T>
.
Aşağıdaki örnek düzeltme eki belge null olarak ayarlanır CustomerName
ve silinir Orders[0]
:
[
{
"op": "remove",
"path": "/customerName"
},
{
"op": "remove",
"path": "/orders/0"
}
]
Değiştirme işlemi
Bu işlem işlevsel olarak bir remove
ile aynıdır ve ardından bir ile aynıdır add
.
Aşağıdaki örnek düzeltme eki belgesi değerini CustomerName
ayarlar ve değerini yeni Orders[0]
bir nesneyle değiştirirOrder
:
[
{
"op": "replace",
"path": "/customerName",
"value": "Barry"
},
{
"op": "replace",
"path": "/orders/0",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
Taşıma işlemi
- Bir dizi öğesine işaret ederse
path
: öğeyi öğenin konumunafrom
kopyalarpath
, ardından öğesinderemove
birfrom
işlem çalıştırır. - Bir özelliğe işaret ederse
path
: özelliğinfrom
path
değerini özelliğe kopyalar, ardından özelliğinderemove
birfrom
işlem çalıştırır. - Var olmayan bir özelliğe işaret ederse
path
:- Düzeltme eki uygulanacak kaynak statik bir nesneyse, istek başarısız olur.
- Düzeltme eki uygulanacak kaynak dinamik bir nesneyse: özelliği tarafından
from
belirtilen konuma kopyalarpath
ve özelliği üzerinderemove
birfrom
işlem çalıştırır.
Aşağıdaki örnek düzeltme eki belgesi:
- değerini
Orders[0].OrderName
olarakCustomerName
kopyalar. - Null olarak ayarlanır
Orders[0].OrderName
. - öncesine
Orders[1]
giderOrders[0]
.
[
{
"op": "move",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "move",
"from": "/orders/1",
"path": "/orders/0"
}
]
Kopyalama işlemi
Bu işlem işlevsel olarak son move
adım olmadan bir remove
işlemle aynıdır.
Aşağıdaki örnek düzeltme eki belgesi:
- değerini
Orders[0].OrderName
olarakCustomerName
kopyalar. - öncesinin
Orders[1]
Orders[0]
bir kopyasını ekler.
[
{
"op": "copy",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "copy",
"from": "/orders/1",
"path": "/orders/0"
}
]
Test işlemi
tarafından path
belirtilen konumdaki değer, içinde value
sağlanan değerden farklıysa istek başarısız olur. Bu durumda düzeltme eki belgesindeki diğer tüm işlemler başarılı olsa bile PATCH isteğinin tamamı başarısız olur.
İşlem test
genellikle eşzamanlılık çakışması olduğunda güncelleştirme yapılmasını önlemek için kullanılır.
Aşağıdaki örnek düzeltme eki belgesinin ilk değeri CustomerName
"John" ise hiçbir etkisi yoktur, çünkü test başarısız olur:
[
{
"op": "test",
"path": "/customerName",
"value": "Nancy"
},
{
"op": "add",
"path": "/customerName",
"value": "Barry"
}
]
Kodu alma
Örnek kodu görüntüleyin veya indirme. (Nasıl indirilir).
Örneği test etmek için uygulamayı çalıştırın ve aşağıdaki ayarlarla HTTP istekleri gönderin:
- URL:
http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
- HTTP yöntemi:
PATCH
- Üstbilgi:
Content-Type: application/json-patch+json
- Gövde: JSON proje klasöründeki JSON düzeltme eki belge örneklerinden birini kopyalayıp yapıştırın.
ASP.NET Core