Logout: DAPATKAN atau POST?

435

Pertanyaan ini bukan tentang kapan menggunakan GET atau POST secara umum; ini tentang yang direkomendasikan untuk menangani keluar dari aplikasi web. Saya telah menemukan banyak informasi tentang perbedaan antara GET dan POST dalam pengertian umum, tetapi saya tidak menemukan jawaban yang pasti untuk skenario khusus ini.

Sebagai seorang pragmatis, saya cenderung menggunakan GET, karena menerapkannya jauh lebih sederhana daripada POST; cukup letakkan tautan sederhana dan Anda selesai. Ini tampaknya menjadi masalah dengan sebagian besar situs web yang dapat saya pikirkan, setidaknya dari atas kepala saya. Bahkan Stack Overflow menangani keluar dengan GET.

Hal yang membuat saya ragu adalah argumen (meskipun lama) bahwa beberapa akselerator web / proksi mempre-cache halaman dengan pergi dan mengambil setiap tautan yang mereka temukan di halaman, sehingga pengguna mendapatkan respons yang lebih cepat ketika dia mengkliknya. Saya tidak yakin apakah ini masih berlaku, tetapi jika ini masalahnya, maka secara teori pengguna dengan salah satu akselerator ini akan dikeluarkan dari aplikasi begitu dia masuk, karena akseleratornya akan menemukan dan mengambil logout Tautan bahkan jika dia tidak pernah mengkliknya.

Semua yang saya baca sejauh ini menunjukkan bahwa POST harus digunakan untuk "tindakan destruktif", sedangkan tindakan yang tidak mengubah keadaan internal aplikasi - seperti query dan semacamnya - harus ditangani dengan GET . Berdasarkan ini, pertanyaan sebenarnya di sini adalah:

Apakah keluar dari aplikasi dianggap tindakan merusak / apakah itu mengubah keadaan internal aplikasi?

Daniel Liuzzi
sumber
Nah, dengan asumsi Anda mengunjungi situs untuk pertama kalinya, dan tautan logout tidak ada, Anda akan keluar saat Anda masuk. Akan baik-baik saja setelah Anda login kedua kalinya, karena url logout sudah di-cache. Tetapi orang dapat mengasumsikan akselerator yang layak akan dapat memfilter sebagian besar url logout.
HyperCas
2
HyperCas, akselerator yang memfilter URL logout adalah teori yang saya pertimbangkan dan salah satu alasan saya memutuskan untuk mengirim pertanyaan. Saya merasa sedikit enggan untuk hanya mempercayai logika akselerator, dan suatu hari ada pengguna dengan akselerator jelek mengeluh bahwa dia tidak bisa masuk. Apakah Anda tahu apakah mereka mengikuti standar, atau apakah standar itu ada?
Daniel Liuzzi
Akselerator apa pun yang secara otomatis mengirimkan formulir (misalnya) akan menjadi malware IMO ... sama sekali tidak masuk akal untuk berpikir bahwa akselerator akan mengirimkan formulir secara otomatis. Bayangkan Anda mengunjungi Google. Bagaimana cara mengirimkan formulir pencarian? Tidak ada yang dapat menjelaskan Malware karena terlalu tidak dapat diprediksi dan tidak mengikuti aturan.
Alex
3
@ AlexW - Saya pikir Anda salah mengerti pertanyaan saya. Skenario akselerator yang saya usulkan adalah menunjukkan masalah yang mungkin terjadi ketika menggunakan GET, bukan POST, jadi tidak akan ada formulir untuk diposkan, hanya tautan biasa yang tidak diikuti masalah akselerator.
Daniel Liuzzi
1
Saya menyadari bahwa saya sudah bertahun-tahun terlambat untuk ini, tetapi Alex, bukan itu yang ditanyakan Daniel. Dia mengatakan bahwa jika pengguna mengklik tautan logout dan akselerator mengembalikan halaman cache yang di-cache tanpa memukul aplikasi, maka pengguna akan tetap masuk. Tidak ada hubungannya dengan malware, meskipun FYI yang memeriksa string User-Agent tidak akan memperbaiki apapun itu.
Rob Grant

Jawaban:

476

Gunakan POST.

Pada 2010, menggunakan GETmungkin merupakan jawaban yang bisa diterima. Tapi hari ini (tahun 2013), browser akan mengambil lebih awal halaman yang mereka pikir akan Anda kunjungi selanjutnya.

Berikut adalah salah satu pengembang StackOverflow yang membicarakan masalah ini di twitter:

Saya ingin mengucapkan terima kasih kepada bank saya karena membuat logout permintaan GET, dan tim Chrome untuk prefetching URL praktis. - Nick Craver ( @Nick_Craver ) 29 Januari 2013

fakta menyenangkan: StackOverflow digunakan untuk menangani log-out via GET, tetapi tidak lagi.

David Murdoch
sumber
2
Terima kasih atas pembaruan ini, Dave. Saya bahkan tidak melihat SO mengganti logout mereka ke POST, dan saya benar-benar tidak tahu bahwa Chrome datang dengan pre-fetching bawaan. Akhirnya, twit yang Anda kutip tidak akan pernah menawarkan contoh yang lebih baik untuk masalah yang saya jelaskan di pertanyaan saya dan mengkonfirmasi kecurigaan saya. Saya memilih jawaban Anda dan menjadikannya jawaban yang diterima.
Daniel Liuzzi
4
Di browser saya, Stackoverflow logout tampak seperti <li> <a href="https://stackoverflow.com/users/logout"> logout </a> </li> yang merupakan GET, bukan POST
boatcoder
9
@ Mark0978, klik tautannya.
David Murdoch
2
Menarik. Itu mungkin salah satu fitur favorit saya, logout yang kemudian bertanya apakah saya yakin. Tebak itu membuat prefetch dari logout Anda, tetapi Amazon, Ebay, dan Gmail semua menggunakan GET untuk logout tanpa halaman trik di antara apa yang dikatakan pengguna adalah logout dan peristiwa logout yang sebenarnya. Saya akan membayangkan bahwa di antara halaman akan menyebabkan banyak orang secara keliru percaya bahwa mereka keluar. Masalah dengan itu pada SO sangat minim, tidak ada uang yang terlibat, dan 99% dari semuanya adalah publik.
boatcoder
7
@ Merah Menurut standar HTTP / 1.1, ini adalah kesalahan server, bukan browser. GET diharapkan tidak memiliki efek samping di sisi server. Standar itu bahkan mengatakan "pengguna tidak meminta efek samping, jadi karena itu tidak dapat dimintai pertanggungjawaban untuknya".
eyuelt
45

Dalam REST seharusnya tidak ada sesi, oleh karena itu tidak ada yang bisa dihancurkan. Klien REST mengautentikasi pada setiap permintaan. Masuk, atau keluar, itu hanya ilusi.

Apa yang sebenarnya Anda tanyakan adalah apakah browser harus terus mengirim informasi otentikasi pada setiap permintaan.

Boleh dibilang, jika aplikasi Anda memang menciptakan ilusi sedang login, maka Anda harus bisa "logout" menggunakan javascript. Tidak perlu pulang pergi.


Disertasi Fielding - Bagian 5.1.3

setiap permintaan dari klien ke server harus berisi semua informasi yang diperlukan untuk memahami permintaan tersebut, dan tidak dapat memanfaatkan konteks yang tersimpan di server. Karenanya, status sesi disimpan sepenuhnya pada klien

Darrel Miller
sumber
1
Saya sebenarnya tidak menyadari hal ini. Maka saya kira aplikasi saya tidak akan sangat tenang sama sekali, karena saya menggunakan ASP.NET MVC dengan FormsAuthentication dan itu bergantung pada sesi ...
Daniel Liuzzi
19
tetapi dalam praktiknya info login disimpan dalam cookie yang ditandai dengan httponlyatribut untuk mencegah beberapa risiko xss, yang berarti itu hanya dapat diatur ulang dari server (singkat secara manual menghapus cookie)
Remus Rusanu
6
'Manual' seperti pada pengguna pergi ke pengaturan Browser dan memilih opsi 'Bersihkan cookie'. Cara yang hampir tidak dapat diterima untuk 'logout' situs web.
Remus Rusanu
1
@Remus Ahhh, betapa peramban web yang terkenal membuat menulis aplikasi web begitu menyakitkan.
Darrel Miller
1
@ DarrelMiller ya namun tidak mencabut JWT di sisi server adalah kerentanan keamanan. Bahkan jika token tidak disimpan di server, mereka harus dimasukkan daftar hitam ketika pengguna logout / mengubah kata sandi / mengubah peran / berhenti / dll untuk mencegah penyalahgunaan (setidaknya sampai mereka kedaluwarsa).
java-addict301
39

Salah satu cara GETdapat disalahgunakan di sini adalah bahwa seseorang (pesaing mungkin :) memasang tag gambar dengan src="<your logout link>"MANA SAJA di internet, dan jika pengguna situs Anda menemukan halaman itu, ia akan secara tidak sadar keluar.

gua
sumber
4
Tidak, ini tidak benar. Tautan keluar hanya akan berfungsi jika data cookie yang benar dikirim, yang tidak berasal dari domain lain. Dan bahkan jika id sesi disimpan di url, itu tidak akan berfungsi baik karena perubahan ini untuk setiap sesi.
Richard H
4
Wow, saya tidak pernah memikirkan itu! Jadi, ada alasan lain untuk tidak menggunakan GET, dan alasan lain saya tidak mengerti mengapa semua orang melakukannya. Sialan, sekarang aku tergoda untuk memasukkan "image" stackoverflow.com/users/logout juga posting saya dan lihat apa yang terjadi :-D
Daniel Liuzzi
24
src = adalah permintaan browser yang sederhana, tidak berasal dari sisi server, tetapi dari klien. Ini membawa semua cookie dan berasal dari IP pengguna. Itulah mengapa piksel pelacakan iklan berfungsi. Satu-satunya cara untuk menentukan eksploit semacam itu adalah dengan memeriksa perujuk.
raveren
12
SuperLogout.com melakukan hal itu (memuat /logoutURL dalam gambar tersembunyi), dan berfungsi.
Dan Dascalescu
9
re: SuperLogout ... Saya tidak tahu mengapa saya mengklik itu.
MI Wright
21

Agar benar, GET / POST (atau kata kerja lainnya) adalah tindakan pada beberapa sumber daya (ditangani oleh URL) - sehingga umumnya tentang status sumber daya dan bukan tentang status aplikasi. Jadi dengan semangat yang sebenarnya, Anda harus memiliki URL seperti [host name]\[user name]\session, lalu 'HAPUS' akan menjadi kata kerja yang benar untuk tindakan logout.

Menggunakan [host name]\bla bla\logoutsebagai URL bukan benar-benar REST full way (IMO), jadi mengapa berdebat tentang penggunaan GET / POST yang benar di dalamnya?

Tentu saja, saya juga menggunakan GET untuk url logout di aplikasi saya :-)

VinayC
sumber
2
Dalam hal ini, saya kemudian berpendapat bahwa memiliki bagian [nama pengguna] di URL tampaknya tidak perlu, karena pengguna selalu keluar dari (yaitu DELETE) sesi mereka sendiri ; tidak pernah pengguna lain :-)
Daniel Liuzzi
1
Tidak juga - kami mengatakan bahwa sesi adalah sumber daya dan kami ingin menghapusnya. Jadi untuk menyikapi sesi apa pun secara seragam, Anda harus memiliki nama pengguna sebagai bagian dari URL. Argumen Anda sama baiknya dengan mengeluarkan tindakan PUT pada [galeri foto] \ gambar berarti Anda menambahkan ke foto Anda (tersedia di [galeri foto] \ [nama pengguna] \ gambar). Sumber daya yang berbeda harus ditangani secara eksplisit, tidak mungkin ada kesaksian di dalamnya. Situs ini memungkinkan pengguna lain untuk menambahkan gambar ke galeri Anda - itu akan menjadi bagian dari kontrol akses sama seperti Anda dapat memiliki pengguna super yang dapat membunuh sesi siapa pun.
VinayC
1
Secara filosofis, Anda dapat menyebut sesi dan foto sebagai 'sumber', tetapi secara realistis saya tidak akan memperlakukannya sama. Sesi selalu terbatas secara intrinsik untuk pengguna saat ini (maka nama Sesi) dan, setidaknya di ASP.NET, tidak ada cara mengakses sesi pengguna lain. Bahkan pengembang aplikasi tidak memiliki cara langsung untuk menyebutkan semua sesi aktif, atau sarana untuk membunuh sesi secara individual. Anda dapat memulai ulang aplikasi untuk mematikan semua sesi (InProc), tetapi saya tidak akan memanggil kontrol akses itu. Selain URL, pertanyaannya tetap: GET atau POST?
Daniel Liuzzi
Sumberdaya, maka alamatnya (URL) adalah bagian penting dari REST. Jadi jika Anda memilih URL seperti yang saya katakan, HAPUS menjadi kata yang benar - bukan GET atau POST. Juga, bahkan jika Anda membatasi diri untuk ASP.NET, Anda selalu dapat memiliki penyedia negara kustom Anda yang dapat memberi Anda cara untuk menghitung melalui sesi dan membunuh sesi lain jika diperlukan. Untuk sesi in-proc out of box, beberapa mengutak-atik global.asax akan memberi Anda fungsionalitas. Ini benar-benar pertanyaan apakah fungsi seperti itu akan dibutuhkan atau tidak. Untuk kebutuhan yang jarang, orang cenderung memulai kembali situs web untuk mengusir orang dari situs.
VinayC
Ini masuk akal bagi saya. Berikan api sesi web web dan panggil DELETE di atasnya. Baik itu ../sesi atau ../session/current. Thankx @VinayC
Simon Hooper
16

Keluar tidak melakukan apa-apa pada aplikasi itu sendiri. Ini mengubah status pengguna dalam kaitannya dengan aplikasi. Dalam hal ini, tampaknya pertanyaan Anda lebih didasarkan pada bagaimana seharusnya perintah dimulai dari pengguna untuk memulai tindakan ini. Karena ini bukan "tindakan destruktif", yakin bahwa sesi ini ditinggalkan atau dihancurkan tetapi aplikasi atau data Anda tidak diubah, tidak mungkin untuk memungkinkan kedua metode untuk memulai prosedur logout. Pos harus digunakan oleh tindakan yang dilakukan pengguna (misalnya - klik pengguna "Keluar"), sementara get dapat dicadangkan untuk logout yang dimulai oleh aplikasi (misalnya - pengecualian yang mendeteksi potensi intrusi pengguna yang secara paksa diarahkan ke halaman login dengan GET logout. ).

Joel Etherton
sumber
Menarik; Saya tidak pernah memikirkannya seperti ini. +1.
strager
Ini bisa dibayangkan tergantung pada aplikasi (semacam perilaku "cascading delete"), tetapi Anda benar.
Andres Jaan Tack
@ JoelEtherton Terima kasih, Joel, saya sudah membaca jawabannya sambil bertanya-tanya kapan saya akan menjawab yang benar. :)
Kirill Fuchs
4
Ini membingungkan karena status perubahan logout. POST adalah kata kerja untuk mengubah keadaan. GET adalah untuk mendapatkan data tanpa kewarganegaraan. Ini membingungkan karena kami mengharapkan permintaan POST untuk memiliki muatan. Seperti disebutkan di bawah, DELETE akan paling benar pada objek sesi.
Michael Cole
1
@MichaelCole: Saya setuju dengan representasi kesulitan antara POST dan GET. Saya tidak akan setuju dengan penggunaan kata kerja DELETE. DELETE untuk menangani sumber daya, dan sesi ini bukan sumber daya dalam pengertian ini. Pertimbangkan, jika Anda bisa HAPUS, maka Anda juga harus bisa PUT.
Joel Etherton
16

Halo menurut pandangan saya, ketika Anda login Anda memeriksa nama pengguna / kata sandi dan jika mereka cocok Anda membuat token login.

CREAT token => metode POST

Ketika Anda logout, Anda mendistribusi token sehingga bagi saya metode yang paling logis adalah DELETE

DELETE token => method DELETE

miorey
sumber
4
Sudut yang menarik.
Drumbeg
1
Saya menggunakan metode itu di aplikasi Spring Boot REST saya.
Please_Dont_Bully_Me_SO_Lords
1
benar secara semantik. Saya setuju ...
DAG
1

Skenario pre-caching sangat menarik. Tapi saya menduga bahwa jika banyak situs inc jadi jangan khawatir tentang ini maka mungkin Anda juga tidak boleh.

Atau mungkin tautannya bisa diimplementasikan dalam javascript?

Sunting: Seperti yang saya pahami, secara teknis GET harus untuk permintaan hanya-baca, yang tidak mengubah status aplikasi. POST harus untuk permintaan penulisan / edit yang mengubah status. Namun masalah aplikasi lain mungkin lebih suka GET daripada POST untuk beberapa permintaan yang berubah negara, dan saya tidak berpikir ada masalah dengan ini.

Richard H
sumber
Terima kasih. The DB negara tidak akan berubah, tetapi sesi negara akan. Satu-satunya masalah yang saya lihat adalah yang saya sebutkan dalam pertanyaan, tentang pengguna yang dikeluarkan. Non-destruktif tapi agak menyebalkan. Saya biasanya pergi dengan mantra "jika orang besar melakukannya, maka itu harus OK" juga. Saya hanya ingin tahu pendapat orang lain tentang ini.
Daniel Liuzzi
0

Nah, jika Anda membiarkan aplikasi web Anda meninggalkan sesi melalui skrip logout, Anda biasanya juga tidak perlu. Biasanya ada variabel sesi yang unik untuk sesi yang ingin Anda tinggalkan.

rampok
sumber
Bisakah Anda menguraikan "skrip logout"? Saya tidak yakin apakah Anda mengacu pada menetapkan kedaluwarsa cookie (yang tidak menghilangkan kebutuhan cara membiarkan pengguna keluar secara manual.)
Daniel Liuzzi
Skrip logout akan mengakhiri sesi pengguna (sebenarnya: browser) yang memanggilnya. Di ASP.net, sesi adalah objek sisi server yang dapat diabaikan. PHP memiliki sistem yang serupa. Karena browser itu memanggil skrip yang mengakhiri sesi, ia sudah tahu yang mana untuk mengakhiri, menghilangkan kebutuhan untuk variabel POST atau GET.
Rob
1
Ya, saya mengerti sekarang. Saya sudah memiliki skrip pada tempatnya, khususnya FormsAuthentication.SignOut (), tetapi pertanyaan saya adalah tentang bagaimana menjalankan skrip, seperti dalam GET atau POST.
Daniel Liuzzi
Oh, Anda punya url dalam formulir? Tidak masalah jika Anda tidak menyampaikan informasi apa pun kepadanya. Hal terburuk yang bisa terjadi adalah seseorang membuka skrip secara manual, keluar sendiri. Saya bahkan tidak akan menjadikannya bidang formulir jika tidak perlu, tautan ke skrip juga akan berfungsi. Jika Anda DO mengirim informasi ke skrip, saya mungkin akan memilih POST, sehingga tidak menampilkan informasi kepada pengguna (kecuali jika mereka melihat sumber halaman), dan jika mereka menyegarkan mereka akan mendapat peringatan dari browser mereka (halaman kedaluwarsa), yang mungkin diinginkan.
Rob
0

Baru-baru ini saya mengerjakan proyek yang saya gunakan GET untuk Logout Di bawah ini adalah kode di Nodejs Express dan berfungsi dengan baik

router.js Anda

const express = require("express");
router.get("/signout", signout);

controller.js Anda

exports.signout  = (req, res) => {
        res.clearCookie('t'); //clearing cookie, which is 
            //assign to the user during sign in.          
            res.json({message : 'Signout success'});   
        };
xSachinx
sumber
-2

Saya tidak melihat bagaimana cara keluar (menghilangkan hak pengguna) adalah tindakan yang merusak. Itu karena tindakan "logout" harus hanya tersedia untuk pengguna yang sudah masuk kalau tidak itu akan usang.

String yang dibuat secara acak yang terkandung dalam cookie browser Anda semuanya mewakili sesi pengguna Anda. Ada banyak cara untuk menghancurkannya sehingga secara efektif logout hanyalah layanan untuk pengunjung Anda.

Jpluijmers
sumber
2
wgetdalam mode laba-laba dengan cookie sesi yang benar di wiki pribadi adalah hal yang harus saya lakukan sekali. Tentu saja, salah satu URL rayapan pertama adalah /logout.
Helgi
5
Coba buka SuperLogout.com untuk melihat seberapa besar permintaan GET yang destruktif terhadap /logouthalaman. Misalnya, Anda harus masuk ke Gmail lagi, masuk ke obrolan lagi, cari tempat Anda di percakapan Hangout yang telah Anda gulir dll. - dan ini hanya untuk Google.com.
Dan Dascalescu