JavaScript’te innerHTML özelliğinin tanıtılması ve nasıl kullanılacağı
Günümüzün web geliştirme ortamında, web sayfalarının alakalı ve güncel bilgiler içermesini sağlamak önemlidir. Hisse senedi grafiğini, geçerli saati, kullanıcı adını veya zamana veya kullanıcı etkileşimine göre dinamik olarak değişen herhangi bir veriyi görüntülemeniz gerekiyorsa, kullanıcılarınıza en iyi deneyimi sağlamak için bu içeriği düzenli olarak güncellemeniz önemlidir. Neyse ki, dinamik bilgileri HTML öğeleriyle ilişkilendirmek ve mevcut durumlarını zahmetsizce görüntülemek için uygun bir çözümümüz var ve bu, JavaScript’teki innerHTML özelliğidir.
Bu yazılı eğitimde, JavaScript’te innerHTML ve bunun nasıl ve ne zaman kullanılacağı konusunda size rehberlik etmeyi amaçlıyoruz. Ek olarak, bunu okumak, innerHTML’yi nasıl güvenli bir şekilde kullanacağınızı anlamanıza ve olası Siteler Arası Komut Dosyası Çalıştırma (XSS) saldırıları riskini en aza indirmenize yardımcı olacaktır.
JavaScript’te innerHTML nedir?
JavaScript’teki innerHTML özelliği web geliştiricileri için iki amaca hizmet eder:
- Bu özellik, bir HTML öğesindeki HTML içeriğini dize olarak almanıza olanak tanır.
- innerHTML, öğe içeriğini değiştirmenize veya yeni HTML ile değiştirmenize olanak tanır.
Aşağıdaki HTML örneğini göz önünde bulundurun:
<div id="someDivElement">
<span>Hello World</span>
</div>
Bir öğenin içHTML’sine erişmek için öğenin önce getElementById() kullanılarak alınması gerekir:
const someDivElement = document.getElementById("someDivElement");
Daha sonra innerHTML özelliğine erişebilirsiniz:
console.log(someDivElement.innerHTML);
Bu, “<span>Merhaba Dünya</span>” dizesinin çıktısını verecektir. Öğenin innerHTML’sini değiştirmek istiyorsanız bunu şu şekilde yapabilirsiniz:
someDivElement.innerHTML = "<span>Something just like this...</span>";
JavaScript’te innerHTML örneği
Öğelerin mevcut bir görev listesine eklendiği bir görev uygulamasında JavaScript’te innerHTML’nin nasıl kullanılacağını gösteren bir örnek:
const todos = [
"Exercise",
"Have milk",
"Buy bread",
"Walk the dog",
"Sleep timely :)"
];
const todoListPreview = document.getElementById("tdlst-preview"); // Returns an <ol> element
todos.forEach((todo) => {
todoListPreview.innerHTML += `<li>${todo}</li>`;
});</ol>
Bu kod, tüm görev öğelerini <li> etiketleri olarak özel liste öğemize ekler. Diğer kodlarda olduğu gibi innerHTML’de de istisnaların oluşabileceğini unutmamak önemlidir. Yaygın bir istisna, sağlanan HTML dizesi iyi biçimlendirilmediğinde ortaya çıkan SyntaxError’dur. Bu amacı ifade etmek için aşağıdaki örnek önemlidir:
someDivElement.innerHTML = "<span>William Bradley "Brad" Pitt</span>";
Bu durumda, HTML dizesindeki çift tırnak (“”), “Brad” bilinmeyen bir tanımlayıcı olarak yorumlandığından sözdizimi hatasına neden olur.
JavaScript’te innerHTML ne zaman kullanılmamalıdır?
Özellikle değerlerin ayarlanması söz konusu olduğunda, innerHTML kullanımından kaçınılması gereken durumlar vardır. Bunun nedeni, innerHTML’in, Siteler Arası Komut Dosyası Çalıştırma (XSS) saldırılarına potansiyel olarak kapıyı açabilecek <script> etiketi de dahil olmak üzere tüm HTML etiketlerini kabul etmesidir.
XSS saldırıları, saldırganların bir web sayfasına kötü amaçlı kod yerleştirmesine olanak tanıyan web güvenliği açıklarıdır. Şüphelenmeyen bir kullanıcı sayfayı ziyaret ettiğinde, web tarayıcısı, çerezler ve kişisel veriler gibi hassas bilgilere yetkisiz erişime yol açabilecek enjekte edilmiş bir kod yürütür. Saldırganın sunucusuna kullanıcı çerezleri göndererek kullanıcının kimliğine bürünmesine ve kötü amaçlı eylemler gerçekleştirmesine olanak tanıyan kötü amaçlı bir komut dosyasının enjekte edildiği aşağıdaki örneği düşünün:
Neyse ki, World Wide Web Konsorsiyumu (W3C), HTML’ye dinamik işaretleme eklemek için, JavaScript’e innerHTML yoluyla eklenen komut dosyası öğelerinin çalıştırılmaması gerektiğini belirten bir standart yayınladı. Geleneksel komut dosyası enjeksiyon saldırılarına karşı koruma sağlar. Ancak bilgisayar korsanları XSS saldırılarını gerçekleştirmenin alternatif yollarını buldular. <img> etiketinin başka bir örneğine bakalım. Aşağıdaki örnekte, JavaScript kodunu kabul eden ve çalışmasına izin veren bir hata niteliği bulunmaktadır.
<img decoding="async" src="123" onerror="alert('Haha!')">
Tarayıcı bu etiketi ayrıştırdığında URL beklediği için src değeri geçersiz olduğundan hata atar. Bu bir hatayla sonuçlanır ve <img> etiketinin bir hata dinleyicisi olduğundan, özelliğin içindeki JavaScript kodu yürütülür.
JavaScript’te innerHTML kullanırken dikkatli olmak ve kullanıcı tarafından oluşturulan veya geçersiz içeriği uygun şekilde temizlemeden eklemekten kaçınmak önemlidir. Bunun yerine, DOM manipülasyon yöntemlerini veya XSS saldırılarına karşı yerleşik koruma sağlayan çerçeveleri kullanmak gibi öğeleri değiştirmek ve oluşturmak için alternatif yöntemleri düşünün.
XSS güvenlik açığı oluşturmadan innerHTML nasıl kullanılır?
JavaScript’te innerHTML kullanırken XSS güvenlik açıklarından kaçınmak için, özellikle HTML olarak oluşturulurken kullanıcı girişinin temizlenmesi kritik öneme sahiptir. Kullanıcıların innerHTML kullanarak HTML içeriğini veritabanınıza kaydedebileceği WYSIWYG düzenleyicisi gibi özellikler oluştururken, kötü amaçlı kodların eklenmesini önlemek için giriş temizleme önlemlerini uygulamanız gerekir.
HTML temizleme hizmetleri sağlayan çeşitli açık kaynak kitaplıkları mevcuttur. Önerilen kitaplıklardan biri, hem tarayıcı hem de Node.js ortamları için bu HTML temizliğini sağlayan sanitize-html’dir. Sanitize-html kütüphanesini npm kullanarak aşağıdaki gibi kurabilirsiniz:
npm install sanitize-html
Kütüphaneyi kullanmak nispeten basittir. İşte bazı örnekler:
// Using ES module import
import sanitizeHtml from 'sanitize-html';
// Using CommonJS require
const sanitizeHtml = require('sanitize-html');
sanitizeHtml('<img src="x" onerror="alert(1)//">'); // returns ""
sanitizeHtml('<svg><g>'); // returns ""
sanitizeHtml('<p>abc<iframe>def</iframe></p>'); // returns "<p>abcdef</p>"
sanitizeHtml('<table><tr><td>HELLO</td></tr>'); // returns "<table><tr><td>HELLO</td></tr></table>"
sanitizeHtml('<ul><li><a href="//google.com">click</a></li></ul>'); // returns "<ul><li><a href="%5C%22//google.com%5C%22">click</a></li></ul>"
Bu örneklerin, sanitize-html’nin giriş HTML’sinden potansiyel olarak kötü amaçlı kodu nasıl kaldırabileceğini veya çıkarabileceğini gösterdiğini unutmayın. Varsayılan olarak sanitize-html, etiketlere ve niteliklere izin veren ve diğerlerini kaldıran veya sterilize eden önceden tanımlanmış bir kurallar dizisine sahiptir. Ancak belirli koşullara göre özelleştirilebilir. XSS saldırıları riskini önemli ölçüde azaltmak için hem ön uçta hem de arka uçta HTML dizesi girişlerini her zaman temizlemeniz gerektiğini vurgulamak önemlidir.
innerHTML ve createElement karşılaştırması
innerHTML ile createElement’i karşılaştırırken, aşağıda açıkça açıklanan farklılıkları ve bunların kullanımlarını anlamak önemlidir. createElement genellikle daha hızlıdır çünkü tarayıcının bir HTML dizesini ayrıştırmasına ve bir düğüm ağacı oluşturmasına gerek yoktur. Ayrıca JavaScript’teki innerHTML’den farklı olarak olay dinleyicilerinin eklenmesini de içermez. innerHTML kullanıldığında, tarayıcıların değiştirilen öğedeki tüm DOM düğümlerini yeniden oluşturması ve yeniden oluşturması gerekir.
Bununla birlikte, innerHTML, gerçek zamanlı önizlemeli Markdown’dan HTML’ye dönüştürücü gibi belirli dinamik çözümler için daha kullanışlı ve esnek bir yaklaşım olabilir. Bu senaryoda, innerHTML, kodu basitleştiren ve geliştirmeyi kolaylaştıran kullanışlı bir çözüm sunar. createElement kullanarak aynı işlevselliği elde etmeye çalışmak, daha karmaşık ve katı kodlarla sonuçlanır. Daha önce bahsedilen aynı yapılacaklar listesi örneğini kullanalım, ancak innerHTML yerine createElement’i kullanalım:
const todos = [
"Exercise",
"Have milk",
"Buy bread",
"Walk the dog",
"Sleep timely :)"
];
const todoListPreview = document.getElementById("tdlst-preview"); // Returns an <ol> element
todos.forEach((todo) => {
todoListPreview.innerHTML += `<li>${todo}</li>`;
const listItemElement = document.createElement("li");
listItemElement.textContent = todo;
todoListPreview.appendChild(listItemElement);
});</ol>
Bu yaklaşım bu özel sorun için işe yarasa da ölçeklenebilir değildir. Örneğin, zengin bir metin düzenleyici oluşturmak istiyorsanız, her yeni işlev için ayrı bir mantık yazmanız gerekir; bu da kod tabanını daha karmaşık ve bakımı zor hale getirir. Bu gibi durumlarda javascript’te innerHTML’i basit bir HTML temizleyiciyle birlikte kullanmak daha verimli ve pratik bir çözüm sağlar. Dinamik içeriği kolayca yönetmenize olanak tanır ve kullanıcı tarafından oluşturulan veya geçersiz HTML girişini temizleyerek XSS açıklarını önler.
son söz
HTML ile çalışırken ve innerHTML özelliğine değer atarken akılda tutulması gereken bazı hususlar vardır. İçerikten ve güvenliğinden eminseniz JavaScript’te innerHTML kullanılması kabul edilebilir. Ancak içerik kullanıcı tarafından oluşturulmuşsa veya potansiyel olarak kötü amaçlıysa önlem alınması önemlidir.
Yaklaşımlardan biri, doğrudan HTML dizeleri atamak yerine DOM öğelerini dinamik olarak oluşturmak ve değiştirmek için createElement komutunu kullanmaktır. Bu yöntem daha hızlı olabilir ve innerHTML ile ilgili olası XSS açıklarını önleyebilir.
Bir diğer önemli adım, kullanıcı girişini bir veritabanına kaydetmeden veya HTML olarak oluşturmadan önce sterilize etmektir. HTML dizesini XSS’ye dayanıklı hale getirmek için belirli etiketleri ve nitelikleri kaldırabilen açık kaynak temizleme kitaplıkları mevcuttur. XSS saldırıları riskini azaltmak için hem ön uçta hem de arka uçta temizlik yapılması önemlidir. Ön uçta temizleme işlemi, kullanıcı girdi sağladığında oluşturma zamanında yapılmalıdır; arka uçta ise içerik veritabanına kaydedilmeden önce yapılmalıdır. Bu uygulamaları takip ederek ve kullanıcı girişi temizleme önlemlerini kullanarak web uygulamanızın güvenliğini ve bütünlüğünü sağlayabilir ve XSS açıklarıyla ilişkili riskleri azaltabilirsiniz.