# dokumentasi Django 2.2.9.dev20191202104323

# Perlindungan Cross Site Request Forgery

Middleware CSRF dan etiket cetakan menyediakan perlindungan mudah-digunakan terhadap Cross Site Request Forgeries. Jenis serangan ini muncul ketika situs jaringan jahat mengandung tautan, tombol formulir atau beberapa JavaScript yang berusaha melakukan beberapa tindakan pada situs jaringan anda, menggunakan mandat dari pengguna masuk yang mengunjungi situs jahat dalam peramban mereka. jenis terkait dari serangan, 'login CSRF', dimana situs penyerang mengelabui peramban pengguna mejadi masuk kedalam sebuah situs dengan mandat orang lain, juga ditutupi.

Pertahanan pertama terhadap serangan CSRF adalah memastikan bahwa permintaan GET (dan metode 'aman' lainnya, seeprti ditentukan oleh RFC 7231#section-4.2.1) adalah bebas pengaruh samping. Permintaan melalui metode 'tidak aman', seperti POST, PUT, dan DELETE, dapat kemudian dilindungi dengan mengikuti langkah-langkah berikut.

## Bagaimana menggunakannya

Untuk mengambil keuntungan dari perlindungan CSRF dalam tampilan anda, ikuti langkah-langkah ini:

1. Middleware CSRD diaktifkan secara awalan dalam pengaturan `MIDDLEWARE`. Jika anda menimpa pengaturan itu, ingat bahwa `'django.middleware.csrf.CsrfViewMiddleware'` harys datang sebelum tampilan middleware apapun yang menganggap bahwa serangan CSRF telah ditangani.

   Jika anda meniadakan itu, yang tidak dianjurkan, anda dapat menggunakan `csrf_protect()` pada tampilan tertentu anda ingin lindungi (lihat dibawah).

2. Dalam cetakan manapun yang menggunakan formulir POST, gunakan etiket `csrf_token` didalam unsur `<form>` jika formulir adalah untuk internalURL, misalnya:

       <form method="post">{% csrf_token %}

   Ini jangan diselesaikan untuk formulir POST yang sasaran external URL, sejak itu akan menyebabkan token CSRF bocor, membawa pada kerentanan.

3. Dalam fungsi tampilan sesuai, pastikan bahwa `RequestContext` digunakan untuk membangun tanggapan sehingga `{% csrf_token %}` akan bekerja dengan benar. Jika anda sedang menggunakan fungsi `render()`, tampilan umum, atau aplikasi bantuan, anda sudah dilindungi sejak ini semua menggunakan `RequestContext`.

### AJAX

Selagi metode diatas dapat digunakan untuk permintaan POST AJAX, itu memiliki beberapa ketidaknyamanan: anda harus ingat melewatkan token CSRF dalam sebuah data POST dengan setiap permintaan POST. Untuk alasan ini, ada metode lain: pada setiap XMLHttpRequest, setel sebuah penyesuaian kepala `X-CSRFToken` (seperti ditentukan oleh pengaturan `CSRF_HEADER_NAME`) pada nilai dari token CSRF. Ini sering lebih mudah karena banyak kerangka kerja JavaScript menyediakan kaitan yang mengizinkan kepala untuk disetel pada setiap permintaan.

Pertama, anda harus mendapatkan token CSRF. Bagaimana melakukan itu bergantung pada apakah atau tidak pengaturan `CSRF_USE_SESSIONS` dan `CSRF_COOKIE_HTTPONLY` diadakan.

#### Memperoleh token jika `CSRF_USE_SESSIONS` atau `CSRF_COOKIE_HTTPONLY` adalah `False`

Sumber dianjurkan untuk token adalah kue `csrftoken`, yang akan disetel jika anda telah mengadakan perlindungan CSRF untuk tampilan anda seperti diuraikan diatas.

Kue token CSRD dinamakan `csrftoken` secara awalan, tetapi anda dapat mengendalikan nama kue melalui pengaturan `CSRF_COOKIE_NAME`.

Mendapatkan token adalah mudah:

    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i].trim();
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    var csrftoken = getCookie('csrftoken');

Kode diatas dapat disederhanakan menggunakan JavaScript Cookie library untuk mengganti `getCookie`:

    var csrftoken = Cookies.get('csrftoken');

Catatan

Token CSRF juga hadir dalam DOM, tetapi hanya secara tegas disertakan menggunakan `csrf_token` dalam cetakan. Kue mengandung token resmi; `CsrfViewMiddleware` akan memilih kue ke token dalam DOM. Meskipun, anda dijamin memiliku kue jika token hadir dalam DOM, jadi anda harus menggunakan kue!

Peringatan

Jika tampilan anda tidak membangun sebuah cetakan mengandung etiket cetakan `csrf_token`, Django mugkin tidak menyetel kue token CSRF. Ini adalah umum dalam kasus-kasus dimana formulir secara dinamis ditambahkan ke halaman. Untuk mengalamatkan ke kasus ini, Django menyediakan penghias tampilan yang memaksa mengatur kue: `ensure_csrf_cookie()`.

#### Memperoleh token jika `CSRF_USE_SESSIONS` atau `CSRF_COOKIE_HTTPONLY` adalah `True`

Jika anda mengkatifkan `CSRF_USE_SESSIONS` atau `CSRF_COOKIE_HTTPONLY`, anda harus menyertakan token CSRF dalam HTML anda dan baca token dari DOM dengan JavaScript:

    {% csrf_token %}
    <script type="text/javascript">
    // using jQuery
    var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
    </script>

#### Mengatur token pada permintaan AJAX

Akhirnya, anda harus sebenarnya menyetel kepala pada permintaan AJAX anda, selagi melindungi token CSRF dari dikirim ke ranah lain menggunakan settings.crossDomain dalam jQuery 1.5.1 dan terbaru:

    function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });

Jika anda sedang menggunakan Angular JS 1.1.3 dan terbaru, itu cukup mengkonfigurasi penyedia `$http` dengan kue dan nama-nama kepala:

    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

### Menggunakan CSRF dalam cetakan Jinja2

Backend cetakan `Jinja2` Django menambahkan `{{ csrf_input }}` ke konteks dari semua cetakan yang setara pada `{% csrf_token %}` dalam bahasa cetakan Django. Sebagai contoh:

    <form method="post">{{ csrf_input }}

### Cara penghias

Daripada menambahkan `CsrfViewMiddleware` sebagai sebuah lapisa perlindungan, anda dapat menggunakan penghias `csrf_protect`, yang sebenarnya kegunaan sama, pada tampilan tertentu yang butuh perlindungan. Itu harus digunakan both pada tampilan yang memasukkan token CSRF dalam keluaran, dan itu yang menerima data formulir POST. (Ini adalah fungsi tampilan sama yang sering, tetapi tidak selalu).

Gunakan dari penghias oleh itu sendiri adalah not recommended, sejak jika anda melupakan itu, anda akan mempunyai sebuah lubang keamanan. Strategi 'belt and braces' dari menggunakan keduanya adalah baik, dan akan mendatangkan beban minimal.

`csrf_protect`(view)

  Penghias yang menyediakan perlindungan dari `CsrfViewMiddleware` ke sebuah tampilan.

  Penggunaan:

      from django.shortcuts import render
      from django.views.decorators.csrf import csrf_protect

      @csrf_protect
      def my_view(request):
          c = {}
          # ...
          return render(request, "a_template.html", c)

  Jika anda sedang menggunakan tampilan berdasarkan-kelas, anda dapat mengacu ke Decorating class-based views1.

## Permintaan tertolak

Secara awalan, sebuah tanggapan '403 Forbidden' dikirim ke pengguna jika sebuah permintaan datang gaagl melakukan pemeriksaan oleh `CsrfViewMiddleware`. Ini harus biasanya hanya dilihat ketika ada Cross Site Request Forgery asli, atau ketika, karena pada kesalahan pemrograman, token CSRF belum dimasukkan dengan formulir POST.

Halaman kesalahan, bagaimanapun, itu tidak sangat ramah, jadi anda mungkin ingin menyediakan tampilan anda sendiri untuk menangani kondisi ini. Untuk melakukan ini, cukup setel pengaturan `CSRF_FAILURE_VIEW`.

Kegagalan CSRF adalah tercatat sebagai peringatan pada pencatat django.security.csrf 1.

## Bagaimana itu bekerja

Perlindungan CSRF berdasarkan pada hal-hal berikut:

1. Sebuah kue CSRF yaitu berdasarkan pada nilai rahasia acak, yang situs-situs lain tidak akan mengaksesnya.

   Kue ini disetel oleh `CsrfViewMiddleware`. Itu dikirim dengan setiap tanggapan yang telah memanggil `django.middleware.csrf.get_token()` (fungsi digunakan secara internal untuk mengambil token CSRF), jika itu belum disetel pada permintaan.

   Untuk terlindungi terhadap serangan BREACH, token tidak cukup rahasia; sebuah garam acak ditambahkan ke rahasia dan digunakan untuk mengaduk itu.

   Untuk alasan keamanan, nilai dari rahasia berubah setiap waktu pengguna masuk.

2. Sebuah bidang formulir sembunyi dengan nama 'csrfmiddlewaretoken' hadir dalam semua formulir POST keluar. Nilai dari bidang ini adalah, kembali, nilai rahasia, dengan garam yang keduanya ditambahkan ke itu dan digunakan untuk mengacak nya. Garam dibangkitkan kembali pada setiap panggilan pada `get_token()` sehingga nilai bidang formulir berubah dalam setiap tanggapan tersebut.

   Bagian selesai dengan etiket cetakan.

3. Untuk semua permintaan datang yang tidak menggunakan HTTP GET, HEAD, OPTIONS atau TRACE, kue CSRF harus hadir, dan bidang 'csrfmiddlewaretoken' harus hadir dan benar. Jika itu tidak, pengguna akan mendapatkan kesalahan 403.

   Ketika mengesahkan nilai bidang 'csrfmiddlewaretoken', hanya rahasia, bukan seluruhnya token, dibandingkan dengan rahasia dalam nilai kue. Ini mengizinkan penggunaan dari token selalu-berubah. Selagi setiap permintaan mungkin menggunakan token nya sendiri, rahasia tetap umum pada semua.

   Pemeriksaan ini selesai dengan `CsrfViewMiddleware`.

4. Sebagai tambahan, untuk permintaan HTTP, pemeriksaan perujuk ketat oleh `CsrfViewMiddleware`. Ini berarti bahwa bahkan jika sebuah subranah dapat disetel atau dirubah kue-kue pada ranah anda, itu dapat memaksa seorang pengguna untuk menempatkan ke aplikasi anda sejak bahwa permintaan tidak akan datang dari ranah tepat anda sendiri.

   Ini juga membahas serangan seorang-dalam-tengah yang memungkinkan dibawah HTTPS ketika menggunakan sebuah rahasia berdiri sendiri sesi, dikarenakan kenyataan bahwa kepala `Set-Cookie` HTTP (sayangnya) diterima oleh klien bahkan ketika mereka sedang berbicara pada situs dibawah HTTPS. (Pemeriksaan perujuk belum dilakukan untuk permintaan HTTP karena kehadiran dari kepala `Referer` tidak cukup handal dibawah HTTP.)

   Jika pengaturan `CSRF_COOKIE_DOMAIN` disetel, perujuk dibandingkan terhadap itu. Pengaturan ini mendukung subranah. Sebagai contoh, `CSRF_COOKIE_DOMAIN = '.example.com'` akan mengizinkan permintaan POST dari `www.example.com` dan `api.example.com`. Jika pengaturan tidak disetel, kemudian perujuk harus cocok kepala `Host` HTTP.

   Memperluas rujukan diterima diluar rumah saat ini atau ranah kue dapat diselesaikan dengan pengaturan `CSRF_TRUSTED_ORIGINS`.

Ini memastikan bahwa hanya formulir yang asli dari ranah terpercaya dapat digunakan untuk data POST kembali.

It deliberately ignores GET requests (and other requests that are defined as 'safe' by RFC 7231#section-4.2.1). These requests ought never to have any potentially dangerous side effects, and so a CSRF attack with a GET request ought to be harmless. RFC 7231#section-4.2.1 defines POST, PUT, and DELETE as 'unsafe', and all other methods are also assumed to be unsafe, for maximum protection.

Perlindungan CSRF tidak dapat melindungi terhadap serangan seorang-dalam-tengah, jadi gunakan HTTPS dengan HTTP Strict Transport Security. Itu juga menganggap validation of the HOST header dan yang tidak ada cross-site scripting vulnerabilities apapun pada situs anda (karena kerentanan XSS sudah membiarkan seorang penyerang melakukan apapun mengizinkan kerentanan CSRF dan lebih buruk lagi).

Memindahkan kepala `Referer`

To avoid disclosing the referrer URL to third-party sites, you might want to disable the referer on your site's `<a>` tags. For example, you might use the `<meta name="referrer" content="no-referrer">` tag or include the `Referrer-Policy: no-referrer` header. Due to the CSRF protection's strict referer checking on HTTPS requests, those techniques cause a CSRF failure on requests with 'unsafe' methods. Instead, use alternatives like `<a rel="noreferrer" ...>"` for links to third-party sites.

## Tembolok

Jika etiket cetakan `csrf_token` digunakan oleh cetakan (atau fungsi `get_token` dipanggil cara lain), `CsrfViewMiddleware` akan menambah sebuah kue dan sebuah kepala `Vary: Cookie` ke tanggapan. Ini berarti bahwa middleware akan bermain baik dengan middleware cache jika itu digunakan sesuai panduan (`UpdateCacheMiddleware` berjalan sebelum semua middleware lain).

Bagaimanapun, jika anda menggunakan penghias cache pada tampilan masing-masing, middleware CSRF belum bisa menyetel kepala Vary atau kue CSRF, dan tanggapan akan di simpan sementara tanpa salah satu. Dalam kasus ini, pada tampilan apapun yang akan membutuhkan token CSRF untuk dimasukkan anda harus menggunakan penghias `django.views.decorators.csrf.csrf_protect()` dahulu:

    from django.views.decorators.cache import cache_page
    from django.views.decorators.csrf import csrf_protect

    @cache_page(60 * 15)
    @csrf_protect
    def my_view(request):
        ...

Jika anda sedang menggunakan tampilan berdasarkan-kelas, anda dapat mengacu ke Decorating class-based views1.

## Pengujian

`CsrfViewMiddleware` biasanya berupa halaman besar untuk mencoba fungsi tampilan, dikarenakan kebutuhan untuk token CSRF yang harus dikirim dengan setiap permintaan POST. Untuk alasan ini, klien HTTP Django untuk percobaan telah dirubah untuk menyetel bendera di permintaan yang mengendurkan middleware dan penghias `csrf_protect` sehingga mereka tidak lagi menolak permintaan. Dalam setiap kepatuhan lain (misalnya mengirim kue dll.), mereka berperilaku sama.

Jika, untuk beberapa alasan, anda ingin klien percobaan melakukan pemeriksaan CSRF, anda dapat membuat sebuah instance dari klien percobaan yang memaksa pemeriksaan CSRF:

    >>> from django.test import Client
    >>> csrf_client = Client(enforce_csrf_checks=True)

## Batasan

Sub ranah dalam sebuah situs akan dapat menyetel kue pada klien untuk seluruh ranah. Dengan mengatur kue dan menggunakan token berhubungan, sub ranah akan dapat mengelak perlindungan CDRF. Cara satu-satunya mengindari ini adalah memastikan bahwa sub ranah dikendalikan oleh pengguna terpercaya (atau, setidaknya tidak dapat menyetel kue). Catat bahwa bahkan tanpa CSRF, ada banyak kerentanan seperti fiksasi sesi, bahwa memberikan sub ranah pada pihak tidak dipercaya adalah ide buruk, dan kerentanan ini tidak dapat dengan mudah diperbaiki dengan peramban saat ini.

## Kasus tepi

Tampilan-tampilan tertentu dapat memiliki persyaratan tidak biasa yang berarti mereka tidak cocok pola biasa dipertimbangkan disini. Sejumlah kegunaan dapat berguna dalam keadaan seperti ini. Skenario mereka mungkin dibutuhkan digambarkan dalam bagian berikut.

### Keperluan

Contoh dibawah ini menganggap anda menggunakan tampilan berdasarkan-fungsi. Jika anda sedang bekerja dengan tampilan berdasarkan-kelas, anda dapat mengacu pada Decorating class-based views.

`csrf_exempt`(view)

  Penghias ini menandai sebuah tampilan sebagai menjadi pengecualian dari perlinsungan dipastikan oleh middleware. Contoh:

      from django.http import HttpResponse
      from django.views.decorators.csrf import csrf_exempt

      @csrf_exempt
      def my_view(request):
          return HttpResponse('Hello world')

`requires_csrf_token`(view)

  Biasanya etiket cetakan `csrf_token` tidak akan bekerja jika `CsrfViewMiddleware.process_view` atauxsetara seperti `csrf_protect` belum berjalan. Tampilan penghias `requires_csrf_token` dapat digunakan untuk memastikan etiket cetakan tidak bekerja. Penghias ini bekerja mirip pada `csrf_protect`, tetapi tidak pernah menolak permintaan datang.

  Contoh:

      from django.shortcuts import render
      from django.views.decorators.csrf import requires_csrf_token

      @requires_csrf_token
      def my_view(request):
          c = {}
          # ...
          return render(request, "a_template.html", c)

`ensure_csrf_cookie`(view)

  Penghias ini memaksa sebuah tampilan mengirim kue CSRF.

### Skenario

#### Perlindungan CSRF harus ditiadakan untuk hanya sedikit tampilan.

Kebanyakan tampilan membutuhkan perlindungan CSRF, tetapi sedikit tidak.

Pemecahan: daripada meniadakan middleware dan memberlakukan `csrf_protect` ke semua tampilan yang membutuhkan itu, adakan middleware dan gunakan `csrf_exempt()`.

#### CsrfViewMiddleware.process_view tidak digunakan

Ada kasus-kasus ketika `CsrfViewMiddleware.process_view` mungkin tidak berjalan sebelum tampilan anda berjalan - penangan 404 dan 500, sebagai contoh - tetapi anda masih butuh token CSRF dalam sebuah formulir.

Pemecahan: gunakan `requires_csrf_token()`

#### Tampilan tidak terlindungi butuh token CSRF

Mungkin ada beberapa tampilan yang tidak terlindungi dan telah dibebaskan oleh `csrf_exempt`, tetapi masih butuh disertakan token CSRF.

Pemecahan: gunakan `csrf_exempt()` diikuti oleh `requires_csrf_token()`. (yaitu `requires_csrf_token` harus berupa penghias paling dalam).

#### Tampilan butuh perlindungan untuk satu jalur

Sebuah tampilan butuh perlindungan CSRF dibawah hanya satu kumpulan dari situasi, dan tidak boleh memilikinya untuk sisa waktu.

Pemecahan: gunakan `csrf_exempt()` untuk seluruh fungsi tampilan, dan `csrf_protect()` untuk jalur dalam itu yang butuh perlindungan. Contoh:

    from django.views.decorators.csrf import csrf_exempt, csrf_protect

    @csrf_exempt
    def my_view(request):

        @csrf_protect
        def protected_path(request):
            do_something()

        if some_condition():
           return protected_path(request)
        else:
           do_something_else()

#### Halaman menggunakan AJAX tanpa formulir HTML apapun

Sebuah halaman membuat permintaan POST melalui AJAX, dan halaman tidak mempunyai formulir HTML dengan `csrf_token` yang akan menyebabkan kue CSRF diwajibkan dikirim.

Pemecahan: gunakan `ensure_csrf_cookie()` di tampilan yang mengirim halaman.

## Aplikasi bantuan dan dipakai kembali

Karena itu memungkinkan untuk pengembang mematikan `CsrfViewMiddleware`, semua tampilan terkait dalam aplikasi bantuan menggunakan penghias `csrf_protect` untuk memastikan keamanan dari aplikasi ini terhadap CSRF. Dianjurkan bahwa pengembang dari aplikasi digunakan kembali lainnya yang ingin jaminan sama juga menggunakan penghias `csrf_protect` pada tampilan mereka.

## Pengaturan

Sejumlah pengaturan dapat digunakan untuk mengendalikan perilaku CSRF Django:

- `CSRF_COOKIE_AGE`
- `CSRF_COOKIE_DOMAIN`
- `CSRF_COOKIE_HTTPONLY`
- `CSRF_COOKIE_NAME`
- `CSRF_COOKIE_PATH`
- `CSRF_COOKIE_SAMESITE`
- `CSRF_COOKIE_SECURE`
- `CSRF_FAILURE_VIEW`
- `CSRF_HEADER_NAME`
- `CSRF_TRUSTED_ORIGINS`
- `CSRF_USE_SESSIONS`

## Pertanyaan Sering Ditanya

### Apakah memasang pasangan token CSRF berubah-ubah (kue dan data POST) sebuah kerentanan?

Tidak, ini adalah berdasarkan perancangan, Tanpa serangan orang-di-tengah, tidak ada cara untuk seorang penyerang mengirim sebuah kue token CSRF ke peramban korban, jadi sebuah serangan berhasil akan butuh mengambil kue peramban korban melalui XSS atau yang mirip, dimana soerang penyerang biasanya tidak butuh serangan CSRF.

Beberapa alat-alat pemeriksaan keamanan menandai ini sebagai sebuah masalah seperti disebutkan sebelumnya, seorang penyerang tidak dapat mencuri kue CSRF peramban pengguna. "Stealing" atau merubah token milik anda menggunakan Firebug, alat-alat pengembangan Chrome, dll. tidak rentan.

### Apakah sebuah masalah bahwa perlindungan Django CSRF tidak berkaitan ke sebuah sesi secara awalan?

Tidak, ini adalah berdasarkan perancangan. Tidak berkaitan perlindungan CSRF pada sebuah sesi mengizinkan menggunakan perlindungan pada situs seperti pastebin yang menggizinkan pengajuan dari pengguna anonim yang tidak mempunyai sebuah sesi.

Jika anda berharap menyimpan token CSRF dalam sesi pengguna, gunakan pengaturan `CSRF_USE_SESSIONS`.

### Mengapa seorang pengguna menghadapi kegagalan pengesahan CSRF setelah masuk?

Untuk alasan keamanan, token CSRF diputar setiap kali pengguna masuk. Halaman apapun dengan sebuah formulir dibangkitkan sebelum masuk akan tua, token CSRF tidak sah dan butuh dimuat kembali. Ini mungkin terjadi jika seorang pengguna menggunakan tombol kembali setelah masuk atau jika mereka masuk dalam peramban berbeda.