Same Origin Policy – Apa dan Bagaimana Mengatasinya?

Pada artikel sebelumnya telah kita bahas bahwa dengan Javascript, kita tidak dapat melakukan request data ke website lain dikarenakan adanya batasan Same Origin Policy.

Nah pada tutorial kali ini, kita akan membahas segala hal tentang same origin policy ini termasuk bagaimana cara mengatasi batasan yang ada sehingga kita dapat melakukan request data ke website lain menggunakan ajax.

Batasan pada  Same Origin Pilicy  hanya berlaku untuk Javascript saja baik berupa request ajax maupun parsing dokumen HTML (seperti pada iframe). Jika kita menggunakan media lain seperti: CURL pada PHP maka batasan ini tidak berlaku

I. Memahami Same Origin Policy

Di dunia intenet terdapat kebijakan bernama “Same Origin Policy” yang mengatur bagaimana script (Javascript) mengakses resource.

Kebijakan ini mengatur bahwa script (Javascript) hanya boleh mengakses resource pada (1) origin (domain) yang sama atau (2) pada origin yang berbeda dengan syarat diijinkan oleh origin tersebut.

1. Bagaimana Implementasi Same Origin Policy

Secara umum implementasi Same Origin Policy adalah sebagai berikut:

  1. Javascript (melalui browser) melakukan request ke URL yang telah kita tentukan.
  2. Browser meneruskan request tersebut.
  3. Alamat yang kita tuju merespon dengan mengirimkan data ke browser kita.
  4. Browser mengecek HTTP Header pada data tersebut (Pengecekan ini  selalu dilakukan browser pada setiap response yang masuk untuk menentukan apa yang harus dilakukan oleh browser).
  5. Browser mencari apakah pada pada header terdapat properti “Access-Control-Allow-Origin” jika tidak maka data akan diblok. Jika ya, maka akan dicek apakah domain asal Javascript diijinkan untuk mengakses data tersebut, jika ya maka data diteruskan ke Javascript, jika tidak maka data akan diblok.

Untuk lebih jelasnya, perhatikan ilustrasi berikut:

Ilustrasi Implementasi Same Origin Policy

Ilustrasi Implementasi Same Origin Policy

2. Properti  Access-Control-Allow-Origin

Seperti yang telah disampaikan sebelumnya bahwa Same Origin Policy ini kuncinya ada pada properti  Access-Control-Allow-Origin yang ada di HTTP Header.

Jika  Access-Control-Allow-Origin tidak di definisikan, maka dapat dipastikan kita tidak dapat mengakses resource pada website tersebut menggunakan ajax dan umumnya (secara default) properti ini memang tidak didefinisikan.

Untuk mengecek properti ini, silakan buka sebuah website, kemudian lihat bagian HTTP Response headernya, misal saya buka https://medium.com/@steve.yegge/latest?format=json, HTTP Response yang saya peroleh adalah:

Properti “Access Control Allow Origin” Tidak Ditemukan Pada HTTP Response Header

Pada gambar diatas terlihat bahwa tidak ada properti  Access-Control-Allow-Origin  yang artinya  request dari origin berbeda tidak diperbolehkan.

Dengan demikian jika kita mencoba mengakses halaman tersebut menggunakan AJAX, kita akan mendapati error sebagai berikut:

Access Control Allow Origin Error

Access Control Allow Origin Error

3. Access-Control-Allow-Origin Berupa  * (Asterik)

Jika  “Access-Control-Allow-Origin” didefinisikan, maka halaman tersebut dapat diakses oleh domain yang berbeda.

Misal saya buka alamat https://cors-proxy.htmldriven.com/?url=https://medium.com/@steve.yegge/latest?format=json  

Respon Header yang kita peroleh adalah:

Properti Access Control Allow Origin Bernilai Asterik

Properti Access Control Allow Origin Bernilai *

Pada contoh diatas, terlihat properti  Access-Control-Allow-Origin bernilai * (asterik) yang artinya semua origin diperbolehkan mengakses halaman tersebut.

Dengan demikian, dengan Javascript AJAX, siapapun termasuk kita dapat mengakses url tersebut.

4. Access-Control-Allow-Origin Berupa  URL

Selain asterik, properti Access-Control-Allow-Origin dapat berisi alamat  url. Jika berupa url, maka hanya url tersebut yang diperbolehkan untuk mengakses halaman dimaksud.

Alamat URL ini meliputi 1) schema, 2) Domain, dan 3) Port. Perhatikan ilustrasi berikut:

Ilustrasi Schema, Domain, dan Port Pada Origin

Ilustrasi Schema, Domain, dan Port Pada Origin

atau dengan default port 8080

Ilustrasi Schema dan Domain Pada Origin

Ilustrasi Schema dan Domain Pada Origin

Secara default, nomor port adalah 8080, sehingga jika kita tidak mendefinisikan nomor port, berarti port yang digunakan adalah 8080, misal: https://jagowebdev.com:8080 sama juga dengan https://jagowebdev.com

Request dari origin berbeda diperbolehkan asal memiliki kesamaan pada ketiga komponen diatas, misal request dari: https://jagowebdev.com/wp-content/demo/json-pada-javascript/json-medium.php diperbolehkan karena telah memenuhi syarat schema, domain, dan port yang sama.

Namun, request dari  http://info.jagowebdev.com/ atau https://jagowebdev.com/tidak diperbolehkan karena domain dan schemanya (https) sudah berbeda.

II. Mengatasi Batasan Same Origin Policy

Sebenarnya Same Origin Policy ini tidak bisa diterobos, namun demikian, terdapat beberapa cara yang dapat kita tempuh agar tidak terkena batasan Same Origin Policy, antara lain:

  1. Menggunakan Proxy (perantara pihak ketiga).
  2. Menggunakan iframe.
  3. JSONP.

1. Menggunakan Proxy

Cara pertama yang paling dapat diandalkan adalah menggunakan proxy (perantara) yaitu berupa website pihak ke tiga.

Pada metode ini, kita melakukan request ke web proxy, kemudian web proxy meneruskan request tersebut ke website yang ingin kita tuju, selanjutnya hasil request dari web proxy tersebut kita ambil menggunakan ajax.

Perhatikan ilustrasi berikut:

Ilustrasi Request Ajax Dengan Web Proxy

Ilustrasi Request Ajax Dengan Web Proxy Eksternal (https://cors-proxy.htmldriven.com)

Nah, agar data pada web proxy tersebut dapat kita ambil menggunakan ajax, maka dapat dipastikan bahwa web proxy tersebut mendefinisikan  Access-Control-Allow-Origin (biasanya berupa asterik *) sehingga dapat diakses oleh origin yang berbeda.

a. Proxy Eksternal

Proxy Eksternal disini maksudnya web proxy disediakan oleh pihak ketiga yang artinya kita tidak memiliki kontrol atas web server proxy tersebut.

Diinternet terdapat banyak website proxy yang dapat kita gunakan dengan gratis salah satunya adalah: https://cors-proxy.htmldriven.com/

Sebagai contoh kita ambil data dari medium.com, script yang kita gunakan adalah sebagai berikut:

<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    obj = JSON.parse(xhr.responseText);
    console.log(obj);
  }
}

xhr.open('GET', 'https://cors-proxy.htmldriven.com/?url=https://medium.com/@steve.yegge/latest?format=json');
xhr.send();
</script>
Jika kita menggunakan proxy pihak ketiga, tidak disarankan untuk penggunaan jangka panjang, karena kita tidak tahu berapa lama layanan tersebut tersedia untuk itu  sebaiknya gunakan proxy eksternal untuk keperluan insidentil saja.

b. Proxy Internal: Origin Sama

Proxy internal disini maksudnya adalah web proxy yang kita buat sendiri sehingga kita memiliki kontrol penuh atas web server. Model proxy ini biasanya digunakan untuk kepentinya internal kita sendiri.

Sebagai contoh misal pada jagowebdev.com saya buat file dengan nama proxy-medium-jagowebdev.php yang berisi kode untuk mengambil data (dengan PHP bukan dengan AJAX) dari medium.com sebagai berikut:

<?php
$data = file_get_contents('https://medium.com/@steve.yegge/latest?format=json');
echo str_replace('])}while(1);</x>', '', $data);

Script tersebut diatas akan menghasilkan data JSON yang siap untuk di gunakan.

Demo: proxy-medium-jagowebdev.php

pada script diatas saya menggunakan  str_replace('])}while(1);</x>', '', $data)  untuk menghilangkan ])}while(1);</x>  yang ada di depan data JSON. Penggunaan  ])}while(1);</x>  di awal data JSON umum digunakan untuk menghindari JSON Hijacking.

Selanjutnya saya buat file json-medium-jagowebdev.html yang berisi script (javascript) yang akan melakukan request ke file proxy-medium-jagowebdev.php  tersebut.

<!DOCTYPE html>
<html>
<head>
  <title>JSON Dari medium.com Dengan AJAX dan Proxy Internal</title>
</head>
<body>
  <script type="text/javascript">
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
        obj = JSON.parse(xhr.responseText);
        console.log(obj);
      }
    }
    xhr.open('GET', 'https://jagowebdev.com/wp-content/demo/json-pada-javascript/proxy-medium-jagowebdev.php');
  xhr.send();
  </script>
</body>
</html>

Demo: json-medium-jagowebdev.html

c. Proxy Internal: Origin berbeda

Jika proxy berada di domain berbeda, maka kita perlu menambahkan pengaturan  Access-Control-Allow-Origin pad header.

Misal kita buat file  proxy-medium-webdevzoom.php  pada webdevzoom.com, agar file tersebut dapat diakses dari domain https://jagowebdev.com maka kita atur properti  Access-Control-Allow-Origin sebagai berikut:

<?php
header('Access-Control-Allow-Origin:https://jagowebdev.com');
$data = file_get_contents('https://medium.com/@steve.yegge/latest?format=json');
echo str_replace('])}while(1);</x>', '', $data);

Pada contoh diatas, Access-Control-Allow-Origin  saya beri nilai https://jagowebdev.com yang artinya hanya request dari https://jagowebdev.com yang diperbolehkan.

Selanjutya kita buat file  json-medium-external-proxy-webdevzoom.html dengan script sama seperti script sebelumnya, hanya pada baris 15 kita ubah menjadi:

xhr.open('GET', 'https://webdevzoom.com/wp-content/demo/json-pada-javascript/proxy-medium-webdevzoom.php');

Demo:  json-medium-external-proxy-webdevzoom.html

Request diatas tidak error karena halaman  proxy-medium-webdevzoom.php memberitahu browser (melalui HTTP Response header) bahwa domain https://jagowebdev.com diperbolehkan mengakses halaman tersebut.

Access Control Allow Origin Dengan URL Tertentu

Access Control Allow Origin Dengan URL Tertentu

Menggunakan Library

Script Proxy diatas bentuknya sederhana, hanya untuk menunjukkan bagaimana proxy bekerja. Jika kita ingin membuat proxy sendiri yang komprehensif, kita dapat menggunakan library yang sudah ada seperti pada corsproxy atau php-cors-domain-proxy

2. Menggunakan iframe

Dengan iframe, kita dapat meload data website lain, namun demikian jika kita ingin memparse data tersebut menggunakan javascript, kita tetap berada di batasan Same Origin Policy.

Kenapa?

Karena seperti telah disampaikan diawal bahwa segala sesuatu yang kita akses menggunakan javascript harus mematuhi ketentuan “Same Origin Policy”.

Jadi, jika website yang ada di iframe berasal dari origin yang berbeda dan kita akses iframe tersebut menggunakan javascript, maka kita akan mendapati error sebagai berikut:

Error Ketika Mengakses Cross Origin Frame Dengan Javascript

Error Ketika Mengakses Cross Origin iFrame Dengan Javascript

Untuk itu jika origin iframe berbeda, sebaiknya kita gunakan proxy atau JSONP (jika website yang kita tuju menyediakan data dengan format JSONP).

Namun demikian pada kondisi tertentu, ketika kita berada pada domain yang sama kita perlu menyediakan data melalui iframe.

Contoh penerapan iframe pada domain yang sama adalah sebagai berikut:

Misal pada jagowebdev.com saya memiliki file iframe.html yang berisi kode HTML sebagai berikut:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Website</title>
  </head>
  <body>
    <div id="website">Jagowebdev.com</div>
  </body>
</html>

Selanjutnya untuk mengakses data pada file tersebut saya buat file parse-iframe.html dengan isi sebagai berikut:

<!DOCTYPE html>
<html>
  <head>
    <title>Mengambil Data Pada iframe Dengan Javascript</title>
  <head>
  <body>
      <script type="text/javascript">
      var iframe = document.createElement('iframe');
          
      iframe.style.display = 'none';		
      iframe.onload  = function (e) {
        data = iframe.contentDocument || iframe.contentWindow.document;
        website = data.getElementById('website').innerHTML;
        iframe.parentElement.removeChild(iframe);		
        alert(website);
      };
      
      iframe.src = 'iframe.html';
      document.body.appendChild(iframe);
    </script>
  </body>
</html>

Demo: parse-iframe.html

3. Menggunakan JSONP

Cara terakhir yang dapat kita gunakan adalah menggunakan JSONP (Json dengan Padding). Dengan JSONP tidak ada batasan “Same Origin Policy”

JSONP ini berbentuk data JSON yang berada di dalam pemanggilan fungsi Javascript, misal:

my_function({"website":"Jagowebdev.com"})

Contoh penggunaan JSONP dapat dibaca pada artikel:  JSONP Dengan Javascript dan jQuery – Lintas Domain

Meski tidak ada batasan, penggunaan JSON memiliki kelemahan utama yaitu  website yang dituju harus menyediakan data dalam bentuk JSONP

dan ternyata.. tidak banyak website yang menyediakan JSONP, jadi gunakan JSONP jika memang memungkinkan untuk menggunakannya.

Pertanyaan selanjutnya, bagaimana jika kita memiliki akses ke web server dan dengan mudan dapat menyediakan data dengan format JSONP?

Pada kondisi demikian, opsi terbaik tetaplah menggunakan Access-Control-Allow-Origin namun dengan tetap membatasi hanya domain tertentu saja yang dapat megakses resource kita.

Karena dengan model seperti itu penulisan script untuk pengambilan data akan lebih mudah fleksibel dibanding menggunakan JSONP.

Lebih lengkap tentang JSONP dapat dibaca di:  JSONP Dengan Javascript dan jQuery – Lintas Domain

Demo penggunaan JSONP: JSONP Dari Flickr.com

III. Kesimpulan

Didalam dunia website terdapat kebijakan bernama “Same Origin Policy” yang mengatur bagaimana Javascript mengakses resourse, baik resource pada origin (domain) yang sama maupun pada origin berbeda.

Inti dari kebijakan Same Origin Policy adalah: untuk alasan keamanan, Javascript hanya diperbolehkan mengakses resource pada origin yang sama atau origin yang berbeda jika sudah mendapat ijin dari resoure tersebut.

Untuk mengatasi batasan Same Origin Policy ini, ada beberapa metode yang dapat kita gunakan, metode yang paling handal adalah menggunakan proxy, karena penggunaannya lebih mudah dan fleksibel.

Demikian pembahasan mengenai Same Origin Policy, semoga bermanfaat.

Subscibe Now

Suka dengan artikel di Jagowebdev.com? jangan sampai ketinggalan, segera join ke milis kami untuk update informasi terbaru dari Jagowebdev.com

Komitmen Kami: Kami senantiasa menghargai privasi Anda dan tidak akan membagikan identitas Anda ke pihak manapun.

2 Feedback dari pembaca

  • Terima kasih atas ilmunya master…
    saya mau tanya, bokehkan…
    bagaimanakah caranya kalau mau mengatasi batasan cors policy untuk mengakses file playlist m3u8?

Silakan tinggalkan komentar

Newsletter

Jadilah yang pertama tahu berita terbaru dari Jagowebdev.com