Sesi aktif. Sesi. Kata laluan aplikasi Facebook

Mari kita lihat konsep sesi (sesi HTTP, Sesi). Atau dengan kata lain, sesi pengguna. Mengapakah penting untuk memahami cara sesi berfungsi? Dan mari lihat bagaimana kita boleh bekerja dengan keadaan sesi dalam platform ASP.NET.

Sebelum kita mentakrifkan istilah "sesi", mari kita lihat sedikit pada latar belakang, sebab keperluan untuk sesi timbul sejak awal, dan pertimbangkan satu ciri protokol HTTP.

Salah satu ciri utama protokol HTTP ialah ia tidak mewajibkan pelayan untuk menyimpan maklumat tentang klien antara permintaan, iaitu, untuk mengenal pasti klien. Ini adalah protokol tanpa kewarganegaraan yang dipanggil. Sambungan antara klien dan pelayan tamat sebaik sahaja pemprosesan permintaan semasa selesai. Setiap permintaan baharu kepada pelayan diandaikan sepenuhnya unik dan bebas, walaupun ia dihantar berulang kali daripada sumber yang sama.

Bagaimana jika kami meninggalkan sifat tanpa kewarganegaraan protokol HTTP dan tidak mengenal pasti pengguna? Keadaan sesi boleh dielakkan dengan mudah jika tapak anda memaparkan maklumat statik (tanpa nama), seperti artikel berita yang terdiri daripada teks dan imej. Dalam konteks ini, adalah tidak perlu untuk mengaitkan berbilang permintaan dengan satu pengguna. Lagipun, kandungan artikel tidak akan berubah dalam apa jua cara, sama ada sepuluh permintaan daripada satu peranti, atau sepuluh permintaan daripada orang yang berbeza daripada peranti yang berbeza.

Tetapi sebaik sahaja kami akan memindahkan maklumat peribadi ke pelayan, kami perlu memastikan bahawa pelayan mengaitkan semua permintaan kami dengan kami, dan pada masa hadapan dengan betul mengenal pasti semua permintaan yang datang daripada kami. Jika anda tidak melakukan ini, kami akan dipaksa untuk menghantar semula data peribadi yang diperlukan dengan setiap permintaan baharu. Contohnya, log masuk untuk memasukkan akaun peribadi anda di tapak web, atau maklumat seperti nama, alamat penghantaran, semasa membuat pembelian di kedai dalam talian.

Tepatnya dalam situasi seperti ini, apabila kami perlu memperibadikan permintaan daripada satu pelanggan, kami akan menggunakan sesi.

Sesi (sesi)- ini ialah tempoh masa tertentu di mana aplikasi web boleh menentukan semua permintaan daripada satu pelanggan.

Apabila pelanggan pertama kali menyerahkan data peribadi dalam permintaan, sesi baharu dibuat pada pelayan untuk pelanggan tersebut. Sepanjang hayat sesi, semua permintaan daripada pelanggan ini akan diiktiraf secara unik dan dikaitkan dengannya. Selepas masa ini, sambungan dengan pelanggan akan hilang, dan permintaan seterusnya daripadanya akan diproses sebagai benar-benar unik, sama sekali tidak berkaitan dengan yang sebelumnya.

Contohnya, apabila membuat pembelian di kedai dalam talian, maklumat peribadi pengguna disimpan dalam sesi semasa dia menavigasi tapak. Ini ialah item yang dipilih dalam troli, alamat penghantaran, maklumat hubungan dan sebagainya.

Sekarang mari kita lihat bagaimana kita boleh melaksanakan ini secara teknikal. Secara umum, terdapat beberapa teknik untuk menguruskan sesi pelanggan, bilangan dan kaedah pelaksanaannya bergantung pada platform web atau teknologi yang berjalan pada pelayan. Dalam tutorial ini kami akan membincangkan perkara berikut:

  1. medan tersembunyi pada borang HTML
  2. biskut
  3. sesi (sesi, Keadaan sesi)

Mari cuba laksanakannya menggunakan platform ASP.NET. Mari kita lihat secara ringkas dua mekanisme pertama, dan beri perhatian khusus kepada yang ketiga, kerana ia lebih dipercayai, mudah dan selamat.

Medan borang tersembunyi

Intipati pendekatan ini ialah kami menyediakan navigasi tapak menggunakan borang HTML standard. Dan dengan setiap permintaan seterusnya, kami menyimpan data daripada yang sebelumnya dalam medan tersembunyi pada borang. Sebagai contoh:

@using (Html.BeginForm("Forms2", "Home", FormMethod.Post)) (

Pesan hidangan

}

Public ActionResult Forms2() ( ViewBag.UserName = Request.Form["userName"]; return View(); )

@using (Html.BeginForm("Forms3", "Home", FormMethod.Post)) (

@($"Selamat tengah hari (ViewBag.UserName)! Apa yang akan anda pesan?")

}

Dalam contoh ini, kami mendapat nama pengguna pada borang html pertama. Seterusnya dalam pengawal dalam kaedah Borang2() kami mendapatkan semula nilai ini daripada koleksi Borang dan hantar ke paparan melalui objek ViewBeg. Paparan ini menjana kod untuk borang baharu dan menyimpan nama pengguna dalam medan tersembunyi. Oleh itu, nilai nama pengguna akan dipindahkan ke borang ketiga bersama dengan maklumat tambahan - nilai medan dengan nama "foodName". Dan sebagainya.

Mari kita lihat ciri-ciri pendekatan ini. Hampir tidak ada kelebihan, kecuali teknik ini boleh dilaksanakan dengan cepat. Tetapi sekali lagi, pendekatan lain juga boleh dilaksanakan dengan cepat. Tetapi terdapat beberapa kelemahan, dan yang agak ketara:


biskut

Public ActionResult Cookies2() ( HttpCookie cookie = new HttpCookie("userName", HttpUtility.UrlEncode(Request.Borang["userName"])); cookie.Expires = DateTime.UtcNow.AddHours(1); Response.Cookies.Add( kuki); return View(); )

@using (Html.BeginForm("Cookies3", "Home", FormMethod.Post)) (

@($"Selamat tengah hari (HttpUtility.UrlDecode(Request.Cookies["Nama pengguna"]?.Value))! Apakah yang akan anda pesan?")

}

Dalam pendekatan ini, kami tidak menyimpan data sesi secara langsung pada borang; sebaliknya, kami menggunakan mekanisme kuki standard antara klien dan pelayan. Semua data pengguna disimpan dalam kuki.

Apabila memilih pendekatan ini, sekali lagi, masalah utama kekal keselamatan data kami yang kami pindahkan ke pelayan - ia adalah mudah untuk menggantikan atau mencuri, ia adalah dalam teks yang jelas. Selain itu, jika tetapan privasi penyemak imbas pelanggan melumpuhkan penerimaan kuki daripada tapak, maka pilihan untuk mengekalkan sesi ini tidak akan berfungsi sama sekali.

Oleh itu, sangat tidak disyorkan untuk menghantar data penting dan rahsia menggunakan dua kaedah pertama, seperti log masuk, kata laluan, nombor kad, nombor akaun, data pasport, tempat kediaman, dsb.

Mekanisme pengurusan sesi pelayan (Session, SessionState)

Mari kita lihat bagaimana mekanisme sesi berfungsi di bahagian pelayan dan di bahagian klien.

Dengan tetapan keadaan sesi standard, keadaan sesi yang dipanggil digunakan untuk menjejaki satu siri permintaan daripada satu pelanggan. kuki sesi. Algoritmanya adalah seperti berikut:

  1. Untuk setiap permintaan baharu kepada pelayan (tidak kira sama ada pelanggan berbeza atau sama), ASP.NET menjana pengecam sesi yang unik.
    ID sesi ialah nombor yang dijana secara rawak yang dikodkan menggunakan algoritma khas ke dalam rentetan 24 aksara. Rentetan terdiri daripada huruf kecil huruf A hingga Z, serta nombor dari 0 hingga 5. Contoh pengecam ialah hjnyuijl1pam3vox2h5i41in
  2. Jika semasa permintaan semasa, data pelanggan TIDAK disimpan untuk kerja selanjutnya dengannya, maka jangka hayat sesi pelanggan ini berakhir (sebenarnya, tanpa dimulakan). Dalam kes ini, pengecam sesi yang dijana sebelum ini menjadi tidak sah (kerana ia tidak digunakan). Sebagai tindak balas kepada permintaan sedemikian, pelanggan tidak menerima apa-apa untuk mengaitkannya dengan sesi baharu.
  3. Jika data pelanggan (contohnya, nama, alamat penghantaran) disimpan pada pelayan, ASP.NET mengaitkan data yang disimpan dengan pengecam sesi yang dijana sebelum ini. Seterusnya, kuki sesi khas dibuat, dan pengecam ini turut direkodkan di dalamnya. Kuki ini ditambah sebagai tindak balas kepada permintaan dan disimpan dalam penyemak imbas pelanggan. Ini mewujudkan hubungan antara pelanggan dan maklumat peribadinya pada pelayan. Sesi baharu telah dibuat untuk pelanggan ini.
  4. Dengan setiap permintaan berikutnya, pelanggan menghantar pengecam sesi peribadi kepada pelayan melalui kuki. Pelayan sepadan dengan pengecam dan "mengiktiraf" klien dalam sesi semasa.
  5. Selagi pelanggan menghantar kunci peribadinya, sesi itu dianggap aktif. Sesi boleh tamat atas pelbagai sebab, contohnya, secara manual di bahagian pelayan atau selepas masa yang ditetapkan tertentu telah berlalu (tamat masa).

Mari kita beralih dari teori kepada amalan. Mari atur cara algoritma ini dan lihat bagaimana ia berjalan. Untuk melakukan ini, kami menggunakan kelas khas HttpSessionState. Apabila bekerja dalam pengawal, anda boleh menggunakan sifat HttpContext.Session. Bekerja dengan sesi adalah sangat mudah, seperti mana-mana NameValueCollection:

Session["userName"] = Request.Form["userName"]; bool isSessionNew = Session.IsNewSession; string sessionId = Session.SessionID;

Dalam sekeping kod ini, kami merekodkan nama pengguna dalam keadaan sesi. Kami mengambil nama ini dari borang html yang dia hantar kepada kami. Selain itu, melalui sifat, kami mengetahui sama ada sesi ini baru dibuat, iaitu, dalam permintaan semasa (jika ya, maka nilai sifat IsNewSession akan menjadi benar) dan pengecam sesi unik. Pengecam ini, selepas memproses permintaan, akan direkodkan secara automatik dalam kuki sesi (jika belum ada) dan dihantar dalam respons kepada klien.

Dalam penyemak imbas pelanggan, anda boleh melihat kuki yang sepadan dan ID sesinya:

Semasa permintaan seterusnya daripada pelanggan ini, mari baca nama yang disimpan sebelum ini daripada sesi. Kami juga akan menamatkan sesi secara paksa. Kerja dengan pelanggan ini selesai, sebagai contoh, semua data telah diproses dan barang telah dihantar.

String userName = Session["userName"].ToString(); //memproses permintaan... Session.Abandon();

Seperti yang anda lihat, bekerja dengan sesi adalah sangat mudah dan mudah. Kebanyakan proses yang dikaitkan dengan pemprosesan sesi berlaku secara automatik di latar belakang. Sememangnya, pembangun boleh campur tangan pada mana-mana peringkat pemprosesan sesi dan membuat pelarasan.

Mari lihat sifat dan kaedah yang paling menarik bagi kelas HttpSessionState, yang paling kerap digunakan dalam kerja:

item- mengembalikan item data mengikut indeksnya
item- mengembalikan item data dengan kuncinya
Alih keluar(indeks)- memadam elemen data mengikut indeksnya
Alih keluar(kunci)- memadam elemen data dengan kuncinya
Kosongkan()- memadam semua data
Kira- mengembalikan jumlah bilangan item data untuk sesi semasa
Abaikan()- menamatkan sesi dengan paksa
ID Sesi- mengembalikan pengecam sesi semasa
IsNewSession- mengembalikan benar jika sesi dibuat sebagai sebahagian daripada permintaan semasa
Masa tamat- mengembalikan bilangan minit yang dibenarkan antara permintaan sebelum sesi tamat (lalai, 20 minit)

Anda boleh menukar tetapan untuk sesi sama ada secara pemrograman dalam kod melalui ahli kelas HttpSessionState, atau melalui konfigurasi aplikasi (). Sebagai contoh:

Dalam konfigurasi di atas, kami menyatakan bahawa tamat masa sesi ialah 40 minit, data sesi pengguna akan disimpan dalam RAM, kuki sesi akan digunakan dan kami juga menukar nama standard kuki tersebut kepada nama kami sendiri.

Dan satu lagi nota penting dari segi keselamatan. Apabila anda menamatkan sesi pengguna menggunakan Session.Abandon(); Kuki sesi, yang menyimpan ID sesi SessionId, tidak dipadamkan dalam penyemak imbas pengguna. Ini bermakna jika pengguna memulakan sesi baharu tidak lama lagi tanpa menutup penyemak imbas, sesi baharunya akan diberikan SessionId yang sama. Adalah dinasihatkan untuk sentiasa memberikan pengecam unik baharu kepada setiap sesi baharu; untuk melakukan ini, kami perlu memadamkan kuki sesi secara manual selepas menutup sesi:

Session.Clear(); //kosongkan sesi Session.Abandon(); //batalkan sesi //kosongkan kuki secara manual seperti Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", "")); //atau kurangkan Response.Cookies seumur hidup ["ASP.NET_SessionId"]. Tamat tempoh = DateTime.Now.AddYears(-30); //ASP.NET_SessionId ialah nama standard kuki sesi, anda boleh memilikinya sendiri

Beginilah keadaan sesi pengguna dijejaki pada platform ASP.NET, menggunakan sesi. Pendekatan ini adalah standard dan disyorkan untuk digunakan apabila perlu untuk menyimpan maklumat tentang pengguna dan mengenal pasti dia antara permintaan kepada pelayan.

Pelayan web tidak mengekalkan sambungan tetap dengan pelanggan, dan setiap permintaan diproses sebagai permintaan baharu, tanpa sebarang sambungan dengan yang sebelumnya.
Iaitu, anda tidak boleh menjejaki permintaan daripada pelawat yang sama mahupun menyimpan pembolehubah untuknya antara paparan halaman individu. Ia adalah untuk menyelesaikan dua masalah ini bahawa sesi dicipta.
Sebenarnya, sesi, secara ringkasnya, ialah mekanisme yang membolehkan anda mengenal pasti pelayar secara unik dan mencipta fail untuk penyemak imbas ini pada pelayan di mana pembolehubah sesi disimpan.

Saya tidak akan menerangkan secara terperinci keperluan untuk mekanisme sedemikian. Ini adalah kes buku teks seperti troli beli-belah dalam e-stor, kebenaran, serta masalah yang tidak sepenuhnya remeh, seperti melindungi bahagian interaktif tapak daripada spam.

Pada dasarnya, agak mudah untuk membuat sesi analog anda sendiri, tidak berfungsi seperti yang terbina dalam PHP, tetapi serupa pada dasarnya. Pada kuki dan pangkalan data.
Apabila meminta skrip, kami melihat sama ada kuki dengan nama tertentu telah diterima. Jika tiada kuki, kemudian tetapkannya dan tulis baris baharu dengan data pengguna ke pangkalan data. Jika terdapat kuki, maka kita membaca data dari pangkalan data. Dengan permintaan lain kami memadamkan rekod lama daripada pangkalan data dan kini kami mempunyai mekanisme sesi sedia. Tak susah pun. Tetapi terdapat beberapa nuansa yang menjadikannya lebih baik untuk menggunakan mekanisme sesi terbina dalam.

Jika hanya yang pertama didayakan, maka pada permulaan sesi (setiap panggilan session_start()) kuki ditetapkan untuk pelanggan. Penyemak imbas dengan betul mengembalikan kuki ini dengan setiap permintaan berikutnya dan PHP mempunyai pengecam sesi. Masalah bermula jika penyemak imbas tidak mengembalikan kuki. Dalam kes ini, tanpa menerima kuki dengan pengecam, PHP akan sentiasa memulakan sesi baharu dan mekanisme itu tidak akan berfungsi.

Jika hanya yang kedua didayakan, maka kuki tidak ditetapkan. Dan inilah yang berlaku, demi yang, sebenarnya, ia patut menggunakan mekanisme sesi terbina dalam. Selepas skrip menjalankan tugasnya dan halaman terbentuk sepenuhnya, PHP mengimbas keseluruhan halaman dan menambah pengecam sesi pada setiap pautan dan setiap borang. Ia kelihatan seperti ini:
Indeks menjadi
Indeks
dan medan tersembunyi ditambahkan pada borang

Dan penyemak imbas, apabila anda mengklik pada mana-mana pautan, atau apabila anda mengklik butang dalam borang, akan menghantar permintaan pembolehubah yang kami perlukan - pengecam sesi!
Atas sebab yang jelas, pengecam hanya ditambahkan pada pautan relatif.

Secara teorinya, dalam sesi buatan sendiri kami tentang kuki dan pangkalan data, kami boleh menetapkan pemindahan ID secara manual kepada semua pautan - dan kemudian sesi kami sendiri akan berfungsi tanpa mengira kuki. Tetapi adakah anda bersetuju - lebih menyenangkan apabila orang lain melakukan kerja ini? ;-)

Secara lalai, kedua-dua pilihan didayakan dalam versi terbaru PHP. Bagaimanakah PHP mengendalikan ini? Tukang masak sentiasa dipamerkan. Dan pautan dilengkapkan secara automatik hanya jika PHP tidak mengesan kuki dengan pengecam sesi. Apabila pengguna melawat tapak untuk kali pertama semasa sesi ini, kuki diletakkan dan pautan selesai. Pada permintaan seterusnya, jika kuki disokong, PHP melihat kuki dan berhenti melengkapkan pautan. Jika kuki tidak berfungsi, maka PHP terus menambah id pada pautan dengan betul, dan sesi tidak hilang.
Pengguna dengan kuki didayakan hanya akan melihat pautan panjang dengan ID sekali.

Fuh. Pemindahan ID selesai.
Sekarang yang tinggal hanyalah untuk mengikat fail data kepadanya di sisi pelayan.
PHP akan melakukan ini untuk kami. Cukup sekadar menulis
session_start();
$_SESSION [ "ujian" ]= "Hello dunia!" ;

Dan PHP akan menulis pembolehubah ujian pada fail yang dikaitkan dengan sesi ini.
Terdapat nota yang sangat penting di sini.
Susunan $_SESSION- istimewa.
Malah, ia mengandungi pembolehubah yang ingin kami sediakan dalam pelbagai skrip.
Untuk meletakkan pembolehubah dalam sesi, hanya berikannya kepada elemen tatasusunan $_SESSION.
Untuk mendapatkan nilainya, cuma akses elemen yang sama. Contoh akan ada di bawah.

PHP juga mengendalikan pengumpulan sampah - mengalih keluar fail lapuk. Serta pengekodan data dan sekumpulan perkara lain yang perlu. Hasil daripada penjagaan ini, bekerja dengan sesi adalah sangat mudah.
Di sini kita sebenarnya sampai kepada contoh cara sesi berfungsi.
Contoh yang sangat kecil:
session_start();

bergema "Anda telah mengemas kini halaman ini". $_SESSION["kaunter"]++. "sekali." ;
bergema"
kemas kini" ;
?>

Kami menyemak sama ada kami mempunyai pembolehubah pembilang dalam sesi; jika tidak, maka kami menciptanya dengan nilai 0, dan kemudian memaparkan nilainya dan meningkatkannya dengan satu. Nilai yang meningkat akan ditulis pada sesi, dan apabila skrip dipanggil seterusnya, pembolehubah akan mempunyai nilai 1, dan seterusnya.
Semuanya sangat mudah.

Untuk mempunyai akses kepada pembolehubah sesi pada mana-mana halaman tapak, anda perlu menulis HANYA SATU baris (!) pada permulaan SETIAP fail yang kami perlukan sesi:
session_start();
Dan kemudian akses elemen tatasusunan $_SESSION. Sebagai contoh, semakan kebenaran akan kelihatan seperti ini:
session_start();
jika ($_SESSION [ "dibenarkan" ]<> 1 ) {
header("Lokasi: /auth.php");
keluar;
}

Mengalih keluar pembolehubah daripada sesi.
Jika anda mempunyai register_globals=off , maka tulis sahaja
unset($_SESSION [ "var" ]);
Jika tidak, maka dekat Saya perlu menulis dengannya
session_unregister("var");

Ralat yang paling biasa yang PHP hasilkan apabila cuba bekerja dengan sesi adalah yang berikut:
Mereka berdua
Amaran: Tidak boleh menghantar kuki sesi - pengepala sudah dihantar
Amaran: Tidak boleh menghantar pengehad cache sesi - pengepala sudah dihantar

disebabkan oleh sebab yang sama, penyelesaiannya diterangkan dalam benang ini
ketiga,
Amaran: open(/tmp\sess_SID, O_RDWR) gagal: Tiada fail atau direktori (2) sedemikian dalam full_script_path pada nombor baris(sebelum ini dia kelihatan seperti Amaran: Gagal menulis data sesi (fail). Sila sahkan bahawa tetapan semasa session.save_path adalah betul (/tmp)),
jika diterjemahkan daripada bahasa Inggeris, ia menerangkan masalah secara terperinci: laluan ke direktori yang dinyatakan dalam php.ini di mana fail sesi ditulis tidak tersedia. Ralat ini adalah yang paling mudah untuk diperbaiki. Hanya daftarkan direktori yang wujud dan boleh ditulis, sebagai contoh,
session.save_path = c:\windows\temp
Dan jangan lupa untuk memulakan semula Apache selepas ini.

Ternyata, kecerdasan manusia tidak mempunyai had, dan oleh itu saya terpaksa menjelaskan:
mesej tentang ralat ketiga (direktori tidak dapat ditemui) pasti akan membawa kepada kemunculan dua yang pertama, kerana mesej ralat dikeluarkan kepada penyemak imbas dan pengepala selepas ia tidak boleh digunakan. Oleh itu, jangan tergesa-gesa mencari kesimpulan pramatang, tetapi tulis dahulu jalan yang betul!

Masalah paling biasa seterusnya apabila bekerja dengan sesi ialah warisan berat register_globals. JANGAN berikan nama pembolehubah skrip yang sepadan dengan indeks tatasusunan $_SESSION!
Dengan register_globals=pada nilai akan menimpa satu sama lain dan anda akan keliru.
Dan jika register_globals=off, ralat lain akan muncul: "Skrip anda mungkin bergantung pada kesan sampingan sesi yang wujud sehingga PHP 4.2.3.", jika skrip mempunyai pembolehubah sesi yang tidak mempunyai nilai, dan pembolehubah global dengan nama yang sama . Untuk menyingkirkannya, anda mesti sentiasa memulakan pembolehubah sebelum digunakan (atau sekurang-kurangnya menyemak kewujudan) dan tidak memberikan nama pembolehubah global yang bertepatan dengan indeks tatasusunan $_SESSION.

Jika ia tidak berfungsi, tetapi tiada mesej dipaparkan, kemudian tambahkan dua baris pada permulaan skrip yang bertanggungjawab untuk memaparkan SEMUA ralat pada skrin - kemungkinan besar terdapat ralat, tetapi anda tidak melihatnya.
ini_set("display_errors" , 1 );
error_reporting(E_ALL);

atau lihat ralat dalam error_log. Secara umum, topik memaparkan mesej ralat adalah di luar skop artikel ini, jadi pastikan anda sekurang-kurangnya dapat melihatnya. Anda boleh membaca sedikit lagi tentang mencari ralat dalam bahagian ini.

Jika anda pasti bahawa tiada ralat, tetapi contoh yang diberikan tidak berfungsi, maka mungkin PHP tidak membolehkan menghantar id melalui URL, dan kuki atas sebab tertentu tidak berfungsi.
Lihat apa yang tidak kena dengan kuki anda.
Secara umum, jika sesi anda tidak berfungsi, mula-mula cuba hantar pengecam sesi secara manual, iaitu, buat pautan dan tetapkan pengecam kepadanya:
session_start();
if (!isset($_SESSION [ "counter" ])) $_SESSION [ "counter" ]= 0 ;
bergema "Anda telah mengemas kini halaman ini". $_SESSION["kaunter"]++. "sekali.

kemas kini" ;
?>

Walau bagaimanapun, anda harus memastikan arahan session.use_only_cookies tidak didayakan, yang menghalang PHP daripada menerima ID sesi jika ia dihantar melalui URL

Sekiranya contoh ini tidak berfungsi, maka masalahnya sama ada dalam perkara remeh kesilapan silap(separuh daripada "masalah" dengan sesi datang daripada nama pembolehubah yang salah eja), atau dalam versi PHP yang terlalu lama: sokongan untuk sesi muncul dalam versi 4.0 dan tatasusunan $_SESSION- dalam 4.1 (Sebelum ini ia digunakan $HTTP_SESSION_VARS).
Jika ia berfungsi, maka masalahnya adalah pada kuki. Pantau jenis kuki yang ditetapkan oleh pelayan kepada penyemak imbas dan sama ada penyemak imbas mengembalikannya. Ia sangat berguna untuk mencari dengan melihat pertukaran pengepala HTTP antara penyemak imbas dan pelayan.
Penjelasan tentang cara kuki berfungsi adalah di luar skop teks yang sudah terlalu panjang ini, tetapi sekurang-kurangnya pastikan pelayan menghantar kuki dengan pengecam dan penyemak imbas mengembalikannya. Dan pada masa yang sama pengecam bertepatan antara satu sama lain =)
Tetapan kuki sepatutnya kelihatan seperti
Set-Cookie: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6;
atau bagaimana
Set-Cookie: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6; laluan=/
(jika anda meminta skrip bukan dari direktori akar)
Sambutan pelayan sepatutnya kelihatan seperti
Kuki: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6
atau
Kuki: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6; b=b
jika penyemak imbas mengembalikan kuki selain daripada ID sesi.

Jika penyemak imbas tidak mengembalikan kuki, semak sama ada kuki berfungsi sama sekali.
Pastikan domain yang anda akses mempunyai nama biasa (dengan sekurang-kurangnya satu titik dan tiada aksara haram seperti garis bawah) dan kosongkan cache penyemak imbas anda - ini adalah dua sebab utama mengapa kuki mungkin tidak berfungsi.

Jika contoh dari sini berfungsi, tetapi kod anda sendiri tidak, maka masalahnya jelas bukan dalam sesi, tetapi dalam algoritma. Cari tempat anda kehilangan pembolehubah, pindahkan contoh dari sini langkah demi langkah dan nyahpepijat skrip anda.

Masalah lain boleh timbul jika anda menggunakan pengalihan pengepala atau navigasi JavaScript.
Hakikatnya ialah PHP secara automatik menambahkan pengecam sesi hanya pada pautan seperti
, tetapi tidak melakukan ini untuk pengepala, JavaScript, teg meta.
Oleh itu, anda perlu menambah pengecam secara manual, contohnya, seperti ini:
header("Lokasi: /script.php?" . session_name(). "=" . session_id());

Juga, masalah yang sangat jarang berlaku, dan tidak jelas dari mana asalnya, ialah tetapan session.save_handler mempunyai nilai yang berbeza daripada fail. Jika ini tidak begitu, betulkan.

Keselamatan
Keselamatan sesi ialah topik yang luas. Oleh itu, saya akan memberi tumpuan kepada beberapa perkara utama.
Buku teks yang paling banyak adalah tidak menghantar pengecam melalui bar alamat. Ini ditulis walaupun dalam php.ini, tetapi ini mengehadkan kefungsian sesi. Jika anda memutuskan untuk mengikuti nasihat ini, maka sebagai tambahan kepada session.use_trans_sid = 0, jangan lupa session.use_only_cookies = 1
Adalah dinasihatkan untuk mengikat sesi ke alamat IP: dengan cara ini, jika pengecam dicuri, penjahat masih tidak akan dapat menggunakannya dalam kebanyakan kes.
Adalah disyorkan untuk menggunakan arahan session.save_path, yang membolehkan anda menetapkan direktori anda sendiri untuk menyimpan fail sesi. Ini lebih selamat daripada menyimpannya dalam direktori sementara kongsi lalai pelayan.

Maklumat tambahan:

  • Selain kuki, mekanisme sesi juga menghantar pengepala yang melarang caching halaman (penghad cache yang sama). Untuk html ini betul dan perlu. Tetapi apabila anda cuba menghantar fail menggunakan skrip yang menyemak kebenaran, Internet Explorer enggan memuat turunnya. Ini kerana tajuk ini. Panggil
    session_cache_limiter("peribadi");
    mesti menyelesaikan masalah sebelum memulakan sesi.
  • Pelik kerana ia mungkin kelihatan, tetapi dalam array $_SESSION Anda tidak boleh menggunakan indeks berangka - $_SESSION [ 1 ], $_SESSION [ "10" ]- sesi tidak akan berfungsi.
  • Di suatu tempat antara versi 4.2 dan 5.0 tidak mungkin untuk menetapkan session.use_trans_sid menggunakan ini_set(). Bermula dari 5.0 sudah boleh lagi.
  • Sebelum versi 4.3.3 kuki, PHP menghantar kuki hanya jika tiada pengecam dalam permintaan semasa sesi bermula. Kini kuki dihantar pada setiap panggilan session_start()

    Contoh kebenaran menggunakan sesi
    Mari kita menggambarkan semua perkara di atas dengan contoh kecil:
    Mari buat fail auth.php:
    if (isset($_POST [ "nama_auth" ]))
    {
    $sql = "PILIH * DARI pengguna WHERE nama=?s";
    $row = $db -> getRow($sql, $_POST["nama_auth"]);
    if ($row && password_verify ($_POST [ "auth_pass" ], $row [ "pass" ])) (
    $_SESSION [ "user_id" ] = $row [ "id" ];
    }
    header("Lokasi: http://" . $_SERVER [ "HTTP_HOST" ]. $_SERVER [ "REQUEST_URI" ]);
    keluar;
    }

    if (isset($_GET [ "tindakan" ]) DAN $_GET [ "tindakan" ]== "log keluar" ) (
    session_start();
    session_destroy();
    header("Lokasi: http://" . $_SERVER [ "HTTP_HOST" ]. "/" );
    keluar;
    }

    jika (!isset($_SESSION [ "user_id" ])) (
    ?>








    keluar;
    }

    Sekarang semua yang anda perlu lakukan ialah menulis baris dalam semua skrip yang dilindungi
    memerlukan "auth.php" ;
    Contoh ini menganggap bahawa sesi telah pun bermula dan sambungan ke pangkalan data telah dibuat menggunakan Kelas untuk kerja yang selamat dan mudah dengan MySQL. Ia juga menganggap bahawa kata laluan dicincang menggunakan fungsi password_hash yang disyorkan.
    Contoh fail yang dilindungi:

    session_start();
    sertakan "safemysql.class.php" ;
    $db = safemysql baharu ([ "db" => "ujian" ]);
    sertakan "auth.php" ;
    ?>
    rahsia

    log keluar

    OPS! Pautan yang Sangat Berguna:
    http://www.php.net/manual/ru/ref.session.php - maklumat terkini dan terkini tentang sokongan sesi dalam PHP dalam dokumentasi rasmi, serta banyak ulasan pengguna. Bacaan yang sangat disyorkan.
    http://phpclub.ru/manrus/f/ref.session.html - Terjemahan yang SANGAT lapuk bagi bab ini ke dalam bahasa Rusia, daripada dokumentasi yang diterjemahkan oleh Alexander Pyramidin.
    http://phpclub.ru/detail/article/sessions
    Sebuah artikel dengan tajuk yang menyedihkan "The Truth about Sessions." Meninggalkan kesan ambivalen. Pada mulanya, penulis bercakap dengan SANGAT jelas tentang mekanisme sesi, tetapi kaedah yang dia tawarkan pada akhir artikel tidak jelas sama sekali.

    Artikel buku teks oleh Dmitry Borodin dari laman web ini
    http://php.spb.ru/ amat TIDAK disyorkan.
    Lelaki, ia sangat ketinggalan zaman. Ia bukan sahaja mengandungi ketidaktepatan fakta, tetapi sesi dalam PHP sememangnya tidak berfungsi untuk masa yang lama.
    Terima kasih banyak kepada Dima untuk itu, ini adalah artikel pertama mengenai sesi dalam bahasa Rusia, saya belajar darinya sendiri, tetapi sekarang saya perlu menghantarnya ke rehat yang sepatutnya.
    Juga, malangnya, banyak artikel lain yang ada di Internet dan tidak dikemas kini selama bertahun-tahun juga sudah lapuk.

  • Untuk memaparkan halaman ini dengan betul, anda memerlukan penyemak imbas dengan sokongan JavaScript.

    Sesi kebenaran pengguna

    Untuk mengaksesnya anda perlu mengikuti pautan Pengguna aktif Dalam bab Pentadbiran – Halaman Utama dalam blok Pengguna(Gamb. 2); pautan Pengguna aktif Dalam bab Pentadbiran – Sistem – Lesen dalam barisan Lesen kompetitif(Gamb. 3) - pilihan ini hanya boleh dilakukan jika sistem ELMA menggunakanjenis lesen kompetitif ; menekan butang Pengguna aktif Dalam bab Pentadbiran - Pengguna(Gamb. 4).

    nasi. 2. Bahagian "Pentadbiran - Pengguna". Butang Pengguna Aktif

    nasi. 3. Bahagian "Pentadbiran - Sistem - Lesen". Pautan Pengguna Aktif

    nasi. 4. Bahagian "Pentadbiran - Halaman Utama". Pautan Pengguna Aktif

    Nama pengguna– medan ini mengandungi nama penuh. pengguna dalam sistem ELMA. Butang di sebelah nama pengguna membolehkan anda membatalkan (log keluar pengguna yang sepadan) dan mengalih keluar maklumat tentang semua sesi pengguna itu daripada senarai.

    alamat IP– medan ini mengandungi alamat IP pengguna yang kebenarannya dalam sistem dilakukan. Jika ladang web ELMA digunakan untuk kerja, alamat IP sebenar mereka akan dipaparkan untuk setiap pengguna aktif.

    Butang di sebelah alamat IP membolehkan anda menamatkan sesi yang sepadan dan mengalih keluar maklumat mengenainya daripada senarai.

    Ikon di sebelah alamat IP bermakna pengguna semasa sedang diberi kuasa dalam sistem. Selepas masa tertentu telah berlalu sejak respons pengguna terakhir, sesi aktif digantung. Sesi yang dijeda ditandai dengan ikon. Tempoh tamat masa selepas sesi aktif digantung ditakrifkan dalam bahagian Pentadbiran – Sistem – Tetapan Sistem – Tetapan Keselamatan.

    Maklum balas terkini– medan ini mengandungi maklumat tentang tindakan terakhir yang dilakukan oleh pengguna dalam sistem atau tentang permintaan terakhir yang berjaya dihantar dari halaman ke pelayan (sekali seminit permintaan web dihantar dari halaman yang dibuka dalam pelayar ke pelayan ELMA ke semak sambungan dan kumpulkan statistik).

    Tindakan pengguna terakhir– medan ini mengandungi maklumat tentang tindakan terakhir yang dilakukan oleh pengguna dalam sistem dalam format Tarikh – Masa – Pautan ke halaman terakhir yang dilawati oleh pengguna. Pautan ini adalah relatif. Untuk mendapatkan pautan lengkap, anda perlu menambah alamat pelayan padanya (Gamb. 5).

    nasi. 5. Pembentukan alamat penuh pautan ke halaman terakhir yang dilawati oleh pengguna

    Jika tiada aktiviti pengguna untuk masa tertentu, sesi semasa ditamatkan secara automatik. Tetapan tempoh storan sesi dikonfigurasikan dalam bahagian

    Salam, masyarakat yang dikasihi.

    Pertama sekali, saya ingin mengucapkan terima kasih atas sumber yang sangat berguna. Lebih daripada sekali saya telah menemui banyak idea menarik dan nasihat praktikal di sini.

    Tujuan artikel ini adalah untuk menyerlahkan perangkap menggunakan sesi dalam PHP. Sudah tentu, terdapat dokumentasi PHP dan banyak contoh, dan artikel ini tidak bertujuan untuk menjadi panduan lengkap. Ia direka untuk mendedahkan beberapa nuansa bekerja dengan sesi dan melindungi pembangun daripada pembaziran masa yang tidak perlu.

    Contoh penggunaan sesi yang paling biasa ialah, sudah tentu, kebenaran pengguna. Mari kita mulakan dengan pelaksanaan yang paling asas untuk membangunkannya secara beransur-ansur apabila tugas baru timbul.

    (Untuk menjimatkan ruang dan masa, kami akan mengehadkan contoh kami kepada hanya fungsi sesi itu sendiri, dan bukannya membina di sini aplikasi ujian lengkap dengan hierarki kelas yang cantik, pengendalian ralat yang komprehensif dan perkara bagus yang lain).

    Fungsi startSession() ( // Jika sesi telah dimulakan, berhenti melaksanakan dan kembalikan TRUE // (parameter session.auto_start dalam fail tetapan php.ini mesti dilumpuhkan - nilai lalai) jika (session_id()) kembali true; else return session_start(); // Nota: Sebelum versi 5.3.0, fungsi session_start() mengembalikan TRUE walaupun ralat berlaku. // Jika anda menggunakan versi sebelum 5.3.0, lakukan semakan tambahan untuk session_id() // selepas memanggil session_start() ) function destroySession() ( if (session_id()) ( // Jika terdapat sesi aktif, padamkan kuki sesi, setcookie(session_name(), session_id(), time( )-60*60*24); // dan musnahkan session session_unset( ); session_destroy(); ) )

    Catatan: Diandaikan bahawa pembaca mempunyai pengetahuan asas tentang sesi PHP, jadi kami tidak akan merangkumi prinsip operasi fungsi session_start() dan session_destroy() di sini. Tugas susun atur borang log masuk dan pengesahan pengguna tidak berkaitan dengan topik artikel, jadi kami juga akan meninggalkannya. Izinkan saya hanya mengingatkan anda bahawa untuk mengenal pasti pengguna dalam setiap permintaan berikutnya, pada saat log masuk berjaya, kami perlu menyimpan pengecam pengguna dalam pembolehubah sesi (bernama userid, contohnya), yang akan tersedia dalam semua permintaan berikutnya dalam hayat sesi. Ia juga perlu untuk melaksanakan pemprosesan hasil fungsi startSession() kami. Jika fungsi mengembalikan FALSE, paparkan borang log masuk dalam penyemak imbas. Jika fungsi mengembalikan TRUE, dan pembolehubah sesi yang mengandungi pengecam pengguna yang dibenarkan (dalam kes kami - id pengguna), wujud - paparkan halaman pengguna yang dibenarkan (untuk mendapatkan maklumat lanjut tentang pengendalian ralat, lihat tambahan bertarikh 2013-06- 07 dalam bahagian pembolehubah sesi).

    Setakat ini semuanya jelas. Soalan bermula apabila anda perlu melaksanakan kawalan ketidakaktifan pengguna (masa tamat masa), membolehkan berbilang pengguna berfungsi serentak dalam satu penyemak imbas dan juga melindungi sesi daripada penggunaan tanpa kebenaran. Ini akan dibincangkan di bawah.

    Memantau ketidakaktifan pengguna menggunakan alat PHP terbina dalam

    Soalan pertama yang sering timbul dalam kalangan pembangun semua jenis konsol untuk pengguna ialah penamatan automatik sesi sekiranya pengguna tidak aktif. Tidak ada yang lebih mudah daripada melakukan ini menggunakan keupayaan terbina dalam PHP. (Pilihan ini tidak boleh dipercayai atau fleksibel, tetapi kami akan mempertimbangkannya untuk kesempurnaan).

    Fungsi startSession() ( // Tamat masa tidak aktif pengguna (dalam saat) $sessionLifetime = 300; if (session_id()) return true; // Tetapkan kuki seumur hidup ini_set("session.cookie_lifetime", $sessionLifetime); // Jika pengguna tamat masa tidak aktif ditetapkan, tetapkan jangka hayat sesi pada pelayan // Nota: Untuk pelayan pengeluaran, disyorkan untuk pratetap parameter ini dalam fail php.ini jika ($sessionLifetime) ini_set("session.gc_maxlifetime", $sessionLifetime) ; jika (session_start( )) ( setcookie(session_name(), session_id(), time()+$sessionLifetime); return true; ) else return false; )

    Sedikit penjelasan. Seperti yang anda ketahui, PHP menentukan sesi mana yang perlu dilancarkan oleh nama kuki yang dihantar oleh penyemak imbas dalam pengepala permintaan. Penyemak imbas pula menerima kuki ini daripada pelayan, di mana fungsi session_start() meletakkannya. Jika kuki penyemak imbas telah tamat tempoh, ia tidak akan dihantar dalam permintaan, yang bermaksud PHP tidak akan dapat menentukan sesi mana yang hendak dimulakan dan akan menganggap ini sebagai mencipta sesi baharu. Parameter tetapan PHP session.gc_maxlifetime, yang ditetapkan sama dengan tamat masa ketidakaktifan pengguna kami, menetapkan jangka hayat sesi PHP dan dikawal oleh pelayan. Mengawal seumur hidup sesi berfungsi seperti berikut (di sini kami menganggap contoh menyimpan sesi dalam fail sementara sebagai pilihan yang paling biasa dan lalai dalam PHP).

    Apabila sesi baharu dibuat, fail dipanggil sess_ dicipta dalam set direktori sebagai direktori storan sesi dalam parameter tetapan PHP session.save_path , Di mana - pengecam sesi. Seterusnya, dalam setiap permintaan, pada masa melancarkan sesi yang sedia ada, PHP mengemas kini masa pengubahsuaian fail ini. Oleh itu, dalam setiap permintaan berikutnya, PHP, dengan perbezaan antara masa semasa dan masa pengubahsuaian terakhir fail sesi, boleh menentukan sama ada sesi itu aktif atau hayatnya telah pun tamat tempoh. (Mekanisme untuk memadam fail sesi lama dibincangkan dengan lebih terperinci dalam bahagian seterusnya.)

    Catatan: Perlu diingatkan di sini bahawa parameter session.gc_maxlifetime digunakan untuk semua sesi dalam satu pelayan (lebih tepat lagi, dalam satu proses PHP utama). Dalam praktiknya, ini bermakna jika beberapa tapak dijalankan pada pelayan, dan setiap daripadanya mempunyai tamat masa ketidakaktifan pengguna sendiri, maka menetapkan parameter ini pada salah satu tapak akan membawa kepada tetapannya untuk tapak lain. Perkara yang sama berlaku untuk pengehosan kongsi. Untuk mengelakkan situasi ini, direktori sesi berasingan digunakan untuk setiap tapak dalam pelayan yang sama. Menetapkan laluan ke direktori sesi dilakukan menggunakan parameter session.save_path dalam fail tetapan php.ini, atau dengan memanggil fungsi ini_set(). Selepas ini, sesi setiap tapak akan disimpan dalam direktori berasingan dan parameter session.gc_maxlifetime yang ditetapkan pada salah satu tapak hanya akan sah untuk sesinya. Kami tidak akan mempertimbangkan kes ini secara terperinci, terutamanya kerana kami mempunyai pilihan yang lebih fleksibel untuk memantau ketidakaktifan pengguna.

    Mengawal ketidakaktifan pengguna menggunakan pembolehubah sesi

    Nampaknya pilihan sebelumnya, untuk semua kesederhanaannya (hanya beberapa baris kod tambahan), memberikan semua yang kami perlukan. Tetapi bagaimana jika tidak setiap permintaan boleh dianggap sebagai hasil daripada aktiviti pengguna? Sebagai contoh, halaman mempunyai pemasa yang secara berkala membuat permintaan AJAX untuk menerima kemas kini daripada pelayan. Permintaan sedemikian tidak boleh dianggap sebagai aktiviti pengguna, yang bermaksud memanjangkan hayat sesi secara automatik adalah tidak betul dalam kes ini. Tetapi kami tahu bahawa PHP mengemas kini masa pengubahsuaian fail sesi secara automatik setiap kali fungsi session_start() dipanggil, yang bermaksud bahawa sebarang permintaan akan membawa kepada lanjutan hayat sesi dan tamat masa ketidakaktifan pengguna tidak akan berlaku. Selain itu, nota terakhir dari bahagian sebelumnya tentang selok-belok parameter session.gc_maxlifetime mungkin kelihatan terlalu mengelirukan dan sukar untuk dilaksanakan bagi sesetengah orang.

    Untuk menyelesaikan masalah ini, kami akan meninggalkan penggunaan mekanisme PHP terbina dalam dan memperkenalkan beberapa pembolehubah sesi baharu yang akan membolehkan kami mengawal masa ketidakaktifan pengguna sendiri.

    Function startSession($isUserActivity=true) ($sessionLifetime = 300; if (session_id()) return true; // Tetapkan jangka hayat kuki sebelum menutup penyemak imbas (kami akan mengawal segala-galanya di bahagian pelayan) ini_set("session. cookie_lifetime", 0); if (! session_start()) return false; $t = time(); if ($sessionLifetime) ( // Jika tamat masa ketidakaktifan pengguna ditetapkan, // semak masa berlalu sejak aktiviti pengguna terakhir // (masa permintaan terakhir apabila pembolehubah sesi lastactivity dikemas kini) jika (isset($_SESSION["lastactivity"]) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( // Jika masa berlalu sejak aktiviti terakhir pengguna, // adalah lebih besar daripada tamat masa tidak aktif, yang bermaksud sesi telah tamat tempoh dan anda perlu menamatkan sesi destroySession(); return false; ) else ( // Jika tamat masa belum berlaku, // dan jika permintaan itu datang hasil daripada aktiviti pengguna, // kemas kini pembolehubah lastactivity dengan nilai masa semasa, // dengan itu memanjangkan masa sesi dengan detik seumur hidup sesi lain jika ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) kembalikan benar; )

    Mari kita ringkaskan. Dalam setiap permintaan, kami menyemak sama ada tamat masa telah dicapai sejak aktiviti pengguna terakhir sehingga saat semasa, dan jika ia telah dicapai, kami memusnahkan sesi dan mengganggu pelaksanaan fungsi, mengembalikan FALSE. Jika tamat masa belum dicapai, dan parameter $isUserActivity dengan nilai TRUE dihantar ke fungsi, kami mengemas kini masa aktiviti terakhir pengguna. Apa yang perlu kita lakukan ialah menentukan dalam skrip panggilan sama ada permintaan itu adalah hasil daripada aktiviti pengguna, dan jika tidak, panggil fungsi startSession dengan parameter $isUserActivity ditetapkan kepada FALSE.

    Kemas kini dari 2013-06-07
    Memproses hasil fungsi sessionStart().

    Komen menunjukkan bahawa mengembalikan FALSE tidak memberikan pemahaman yang lengkap tentang punca ralat, dan ini benar-benar adil. Saya tidak menerbitkan pengendalian ralat terperinci di sini (panjang artikel sudah agak besar), kerana ini tidak berkaitan secara langsung dengan topik artikel. Tetapi memandangkan komen, saya akan menjelaskan.

    Seperti yang anda lihat, fungsi sessionStart boleh mengembalikan FALSE dalam dua kes. Sama ada sesi tidak dapat dimulakan kerana beberapa ralat pelayan dalaman (contohnya, tetapan sesi yang salah dalam php.ini), atau seumur hidup sesi telah tamat tempoh. Dalam kes pertama, kami mesti mengubah hala pengguna ke halaman dengan ralat yang menyatakan bahawa terdapat masalah pada pelayan dan borang untuk menghubungi sokongan. Dalam kes kedua, kami mesti memindahkan pengguna ke borang log masuk dan memaparkan mesej yang sepadan di dalamnya yang menyatakan bahawa sesi telah tamat tempoh. Untuk melakukan ini, kita perlu memasukkan kod ralat dan mengembalikan kod yang sepadan dan bukannya FALSE, dan dalam kaedah panggilan, semak dan bertindak sewajarnya.

    Sekarang, walaupun sesi pada pelayan masih wujud, ia akan dimusnahkan pada kali pertama ia diakses jika tamat masa tidak aktif pengguna telah tamat tempoh. Dan ini akan berlaku tanpa mengira jangka hayat sesi yang ditetapkan dalam tetapan PHP global.

    Catatan: Apakah yang berlaku jika penyemak imbas ditutup dan kuki nama sesi dimusnahkan secara automatik? Permintaan kepada pelayan pada kali berikutnya penyemak imbas dibuka tidak akan mengandungi kuki sesi, dan pelayan tidak akan dapat membuka sesi dan menyemak tamat masa tidak aktif pengguna. Bagi kami, ini sama dengan mencipta sesi baharu dan tidak menjejaskan fungsi atau keselamatan dalam apa jua cara. Tetapi persoalan yang wajar timbul - siapa yang akan memusnahkan sesi lama, jika sehingga kini kita telah memusnahkannya selepas tamat masa tamat? Atau adakah ia kini akan digantung dalam direktori sesi selama-lamanya? Untuk membersihkan sesi lama dalam PHP, terdapat mekanisme yang dipanggil pengumpulan sampah. Ia berjalan pada masa permintaan seterusnya kepada pelayan dan mengosongkan semua sesi lama berdasarkan tarikh pengubahsuaian terakhir fail sesi. Tetapi mekanisme pengumpulan sampah tidak bermula dengan setiap permintaan kepada pelayan. Kekerapan (atau lebih tepatnya, kebarangkalian) pelancaran ditentukan oleh dua parameter tetapan session.gc_probability dan session.gc_divisor. Hasil pembahagian parameter pertama dengan yang kedua adalah kebarangkalian melancarkan mekanisme kutipan sampah. Oleh itu, agar mekanisme penjelasan sesi dilancarkan dengan setiap permintaan kepada pelayan, parameter ini mesti ditetapkan kepada nilai yang sama, contohnya "1". Pendekatan ini menjamin direktori sesi yang bersih, tetapi jelas terlalu mahal untuk pelayan. Oleh itu, pada sistem pengeluaran, nilai lalai session.gc_divisor ditetapkan kepada 1000, yang bermaksud mekanisme kutipan sampah akan berjalan dengan kebarangkalian 1/1000. Jika anda mencuba tetapan ini dalam fail php.ini anda, anda mungkin dapati bahawa dalam kes yang diterangkan di atas, apabila penyemak imbas menutup dan mengosongkan semua kukinya, masih terdapat sesi lama dalam direktori sesi untuk seketika. Tetapi ini tidak perlu membimbangkan anda, kerana... seperti yang telah dinyatakan, ini tidak sama sekali menjejaskan keselamatan mekanisme kami.

    Kemas kini dari 2013-06-07

    Menghalang skrip daripada membeku kerana penguncian fail sesi

    Komen tersebut membangkitkan isu pembekuan skrip yang dijalankan secara serentak kerana fail sesi disekat (pilihan yang paling menarik ialah tinjauan panjang).

    Sebagai permulaan, saya perhatikan bahawa masalah ini tidak secara langsung bergantung pada beban pelayan atau bilangan pengguna. Sudah tentu, lebih banyak permintaan, lebih perlahan skrip dilaksanakan. Tetapi ini adalah pergantungan tidak langsung. Masalah muncul hanya dalam satu sesi, apabila pelayan menerima beberapa permintaan bagi pihak seorang pengguna (contohnya, salah satunya ialah tinjauan panjang dan selebihnya adalah permintaan biasa). Setiap permintaan cuba mengakses fail sesi yang sama, dan jika permintaan sebelumnya tidak membuka kunci fail, maka permintaan yang berikutnya akan menunggu.

    Untuk memastikan fail sesi terkunci pada tahap minimum, adalah amat disyorkan untuk menutup sesi dengan memanggil fungsi session_write_close() serta-merta selepas semua tindakan dengan pembolehubah sesi telah selesai. Dalam amalan, ini bermakna anda tidak sepatutnya menyimpan segala-galanya dalam pembolehubah sesi dan mengaksesnya sepanjang pelaksanaan skrip. Dan jika anda perlu menyimpan beberapa data yang berfungsi dalam pembolehubah sesi, kemudian bacanya dengan segera apabila sesi bermula, simpannya dalam pembolehubah tempatan untuk kegunaan kemudian dan tutup sesi (bermaksud menutup sesi menggunakan fungsi session_write_close, dan tidak memusnahkannya menggunakan session_destroy ).

    Dalam contoh kami, ini bermakna sejurus selepas membuka sesi, menyemak hayatnya dan kewujudan pengguna yang dibenarkan, kami mesti membaca dan menyimpan semua pembolehubah sesi tambahan yang diperlukan oleh aplikasi (jika ada), kemudian tutup sesi menggunakan panggilan ke session_write_close() dan meneruskan pelaksanaan skrip, sama ada tinjauan panjang atau permintaan biasa.

    Melindungi sesi daripada penggunaan yang tidak dibenarkan

    Cuba kita bayangkan keadaannya. Salah seorang pengguna anda mendapat Trojan yang merompak kuki penyemak imbas (di mana sesi kami disimpan) dan menghantarnya ke e-mel yang ditentukan. Penyerang memperoleh kuki dan menggunakannya untuk menipu permintaan bagi pihak pengguna kami yang dibenarkan. Pelayan berjaya menerima dan memproses permintaan ini seolah-olah ia datang daripada pengguna yang dibenarkan. Jika pengesahan tambahan alamat IP tidak dilaksanakan, serangan sedemikian akan membawa kepada kejayaan penggodaman akaun pengguna dengan semua akibat yang berikutnya.

    Mengapa ini boleh berlaku? Jelas sekali, kerana nama dan pengecam sesi sentiasa sama untuk sepanjang hayat sesi, dan jika anda menerima data ini, anda boleh menghantar permintaan dengan mudah bagi pihak pengguna lain (sudah tentu, sepanjang hayat sesi ini). Ini mungkin bukan jenis serangan yang paling biasa, tetapi secara teorinya ia kelihatan agak boleh dilaksanakan, terutamanya memandangkan Trojan sedemikian tidak memerlukan hak pentadbir untuk merompak kuki penyemak imbas pengguna.

    Bagaimanakah anda boleh melindungi diri anda daripada serangan seperti ini? Sekali lagi, jelas sekali, dengan mengehadkan hayat pengecam sesi dan menukar pengecam secara berkala dalam sesi yang sama. Kami juga boleh menukar nama sesi dengan memadam sepenuhnya yang lama dan mencipta sesi baharu, menyalin semua pembolehubah sesi daripada yang lama ke dalamnya. Tetapi ini tidak menjejaskan intipati pendekatan, jadi untuk kesederhanaan kami akan mengehadkan diri kami kepada hanya pengecam sesi.

    Jelas sekali bahawa semakin pendek jangka hayat ID sesi, semakin sedikit masa penyerang perlu mendapatkan dan menggunakan kuki untuk memalsukan permintaan pengguna. Sebaik-baiknya, pengecam baharu harus digunakan untuk setiap permintaan, yang akan meminimumkan kemungkinan menggunakan sesi orang lain. Tetapi kami akan mempertimbangkan kes umum apabila masa penjanaan semula pengecam sesi ditetapkan sewenang-wenangnya.

    (Kami akan meninggalkan bahagian kod yang telah dibincangkan).

    Function startSession($isUserActivity=true) ( ​​​​ // Session identifier lifetime $idLifetime = 60; ... if ($idLifetime) ( // Jika seumur hidup pengecam sesi ditetapkan, // semak masa berlalu sejak sesi itu dicipta atau penjanaan semula terakhir // (masa permintaan terakhir apabila masa mula pembolehubah sesi dikemas kini) jika (isset($_SESSION["masa mula"])) ( jika ($t-$_SESSION["masa mula"] >= $ idLifetime) ( // Masa hayat pengecam sesi telah tamat // Jana pengecam baharu session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) else ( // Kita sampai di sini jika sesi baru sahaja telah dicipta // Tetapkan masa untuk menjana pengecam sesi kepada masa semasa $_SESSION["starttime"] = $t; ) ) return true; )

    Jadi, apabila mencipta sesi baharu (yang berlaku apabila pengguna berjaya log masuk), kami menetapkan masa mula pembolehubah sesi, yang menyimpan untuk kami masa generasi terakhir pengecam sesi, kepada nilai yang sama dengan masa pelayan semasa. Seterusnya, dalam setiap permintaan, kami menyemak sama ada masa yang mencukupi (idLifetime) telah berlalu sejak generasi terakhir pengecam, dan jika ya, kami menjana yang baharu. Oleh itu, jika dalam tempoh hayat pengecam yang ditetapkan, penyerang yang menerima kuki pengguna yang dibenarkan tidak mempunyai masa untuk menggunakannya, permintaan palsu akan dianggap oleh pelayan sebagai tidak dibenarkan, dan penyerang akan dibawa ke halaman log masuk .

    Catatan: ID sesi baharu masuk ke dalam kuki penyemak imbas apabila fungsi session_regenerate_id() dipanggil, yang menghantar kuki baharu, serupa dengan fungsi session_start(), jadi kami tidak perlu mengemas kini kuki itu sendiri.

    Jika kami ingin menjadikan sesi kami seaman mungkin, sudah cukup untuk menetapkan jangka hayat pengecam kepada satu atau malah mengalih keluar fungsi session_regenerate_id() daripada kurungan dan mengalih keluar semua semakan, yang akan membawa kepada penjanaan semula pengecam dalam setiap permintaan. (Saya belum menguji kesan pendekatan ini pada prestasi, dan saya hanya boleh mengatakan bahawa fungsi session_regenerate_id(true) pada asasnya hanya melaksanakan 4 tindakan: menjana pengecam baharu, mencipta pengepala dengan kuki sesi, memadam yang lama dan mencipta fail sesi baharu).

    Penyimpangan lirik: Jika Trojan ternyata sangat pintar sehingga ia tidak akan menghantar kuki kepada penyerang, tetapi mengatur penghantaran permintaan palsu yang telah disediakan dengan segera selepas menerima kuki, kaedah yang diterangkan di atas kemungkinan besar tidak akan dapat melindungi daripada itu. serangan, kerana antara masa Trojan menerima kuki dan penghantaran permintaan palsu hampir tidak ada perbezaan, dan terdapat kebarangkalian tinggi bahawa pada masa ini pengecam sesi tidak akan dijana semula.

    Kemungkinan kerja serentak dalam satu pelayar bagi pihak beberapa pengguna

    Tugas terakhir yang saya ingin pertimbangkan ialah keupayaan beberapa pengguna untuk bekerja serentak dalam satu pelayar. Ciri ini amat berguna pada peringkat ujian, apabila anda perlu mencontohi kerja serentak pengguna, dan adalah dinasihatkan untuk melakukan ini dalam penyemak imbas kegemaran anda, daripada menggunakan keseluruhan senjata yang tersedia atau membuka beberapa contoh penyemak imbas dalam mod inkognito .

    Dalam contoh terdahulu kami, kami tidak menyatakan nama sesi secara eksplisit, jadi nama PHP lalai (PHPSESSID) telah digunakan. Ini bermakna semua sesi yang kami buat setakat ini telah menghantar kuki ke penyemak imbas di bawah nama PHPSESSID. Jelas sekali, jika nama kuki sentiasa sama, maka tidak ada cara untuk mengatur dua sesi dengan nama yang sama dalam penyemak imbas yang sama. Tetapi jika kami menggunakan nama sesi kami sendiri untuk setiap pengguna, masalah itu akan diselesaikan. Jom buat.

    Function startSession($isUserActivity=true, $prefix=null) ( ... if (session_id()) return true; // Jika awalan pengguna diluluskan dalam parameter, // tetapkan nama sesi unik yang merangkumi ini awalan, // sebaliknya tetapkan nama biasa untuk semua pengguna (contohnya, MYPROJECT) session_name("MYPROJECT".($prefix ? "_".$prefix: ""));ini_set("session.cookie_lifetime", 0); jika (! session_start()) return false; ... )

    Kini yang tinggal hanyalah untuk memastikan bahawa skrip panggilan melepasi awalan unik untuk setiap pengguna ke fungsi startSession(). Ini boleh dilakukan, sebagai contoh, dengan menghantar awalan dalam parameter GET/POST bagi setiap permintaan atau melalui kuki tambahan.

    Kesimpulan

    Kesimpulannya, saya akan menyediakan kod akhir lengkap fungsi kami untuk bekerja dengan sesi PHP, termasuk semua tugas yang dibincangkan di atas.

    Fungsi startSession($isUserActivity=true, $prefix=null) ( $sessionLifetime = 300; $idLifetime = 60; if (session_id()) return true; session_name("MYPROJECT".($prefix ? "_".$prefix: "")); ini_set("session.cookie_lifetime", 0); if (! session_start()) return false; $t = time(); if ($sessionLifetime) ( if (isset($_SESSION["lastactivity"] ) && $t-$_SESSION["lastactivity"] >= $sessionLifetime) ( destroySession(); return false; ) else ( if ($isUserActivity) $_SESSION["lastactivity"] = $t; ) ) if ($idLifetime ) ( if (isset($_SESSION["starttime"])) ( if ($t-$_SESSION["starttime"] >= $idLifetime) ( session_regenerate_id(true); $_SESSION["starttime"] = $t; ) ) else ( $_SESSION["starttime"] = $t; ) ) return true; ) function destroySession() ( if (session_id()) ( session_unset(); setcookie(session_name(), session_id(), time() -60*60*24); session_destroy(); ) )

    Saya harap artikel ini dapat menjimatkan sedikit masa bagi mereka yang tidak pernah mendalami mekanisme sesi, dan memberikan gambaran yang cukup tentang mekanisme ini untuk mereka yang baru mula berjinak-jinak dengan PHP.

    Bab Sesi aktif pada halaman "Tetapan Keselamatan" menunjukkan senarai kes terbaru akses ke akaun Facebook anda.

    Setiap entri mengandungi tarikh dan masa log masuk, anggaran lokasi log masuk berlaku dan jenis peranti yang digunakan untuk log masuk ke akaun. Terdapat juga pilihan untuk menamatkan sesi di sebelah kanan setiap entri.

    Catatan: Lokasi ditunjukkan berdasarkan alamat IP dari mana akaun itu diakses. Jika anda ingin mengetahui butiran tepat mengenai alamat IP log masuk, hanya tuding tetikus anda pada maklumat lokasi sesi.

    Apakah maksudnya apabila saya tidak mengenali titik masuk?

    Jika anda melihat lokasi yang anda tidak kenali, semak dahulu sama ada sesi itu tidak dikaitkan dengan peranti mudah alih. Apabila log masuk menggunakan peranti mudah alih, alamat IP dinamik sering digunakan, yang tidak menggambarkan lokasi fizikal pengguna.

    Jika anda tidak tahu lokasi dan ia tidak dikaitkan dengan log masuk menggunakan peranti mudah alih, sebabnya mungkin seperti berikut:

    Kata laluan aplikasi Facebook

    Apakah kata laluan aplikasi

    Kata laluan aplikasi ialah kata laluan sekali yang digunakan untuk log masuk ke program. Menggunakan kata laluan apl akan membantu memastikan Facebook selamat.

    Selain itu, jika perkhidmatan pengesahan pendaftaran didayakan apabila kata laluan apl digunakan, tidak perlu menunggu kod diterima. Sebaliknya, anda boleh melangkau pengesahan log masuk dan log masuk dengan segera.

    Untuk mendapatkan kata laluan aplikasi:

    pengesahan log masuk Facebook

    Apakah ciri Pengesahan Log Masuk?

    Pengesahan log masuk ialah ciri keselamatan tambahan untuk akaun Facebook anda. Pemberitahuan Log Masuk, tetapi dengan langkah prosedur keselamatan tambahan.

    Selepas anda mendayakan pengesahan log masuk, anda mungkin diminta memasukkan kod log masuk setiap kali anda cuba mengakses akaun Facebook anda daripada komputer atau peranti mudah alih yang tidak dikenali.

    Sebaik sahaja anda log masuk, anda akan mempunyai pilihan untuk memberikan nama peranti ini dan menyimpannya ke akaun anda. Anda tidak perlu memasukkan kod semasa log masuk dari salah satu peranti rasmi.

    Untuk mendayakan ciri pengesahan log masuk:


    Catatan:Untuk membolehkan Pengesahan Log Masuk, anda mesti menyimpan nombor telefon anda dalam data akaun anda.

    Bagaimana untuk menyekat akses ke Facebook tanpa kod

    Jika anda tidak mahu sesiapa sahaja boleh log masuk ke akaun anda dari mana-mana sahaja, anda boleh mendayakan Pengesahan pendaftaran.

    Selepas mendayakan ciri ini, setiap kali anda cuba mengakses akaun anda daripada peranti yang tidak dikenali (contohnya, komputer atau telefon mudah alih), anda mungkin dikehendaki memasukkan kod log masuk.

    Apa yang berlaku jika saya cuba log masuk dari komputer lain?

    Apabila anda cuba log masuk dari peranti yang tidak dikenali, mesej akan muncul meminta anda memasukkan kod log masuk.

    Jika anda telah memasang apl Penjana Kod, buka apl Android Facebook dan dapatkan kod tersebut.

    Jika aplikasi tidak dipasang, semak kod keselamatan pada telefon anda, masukkannya dan gunakan perkhidmatan tersebut. Jika anda menghadapi masalah menerima kod keselamatan, tunggu beberapa minit dan minta kod baharu menggunakan pautan Hantar kod semula. Untuk maklumat lanjut tentang penyelesaian masalah, klik pada pautan Saya tidak dapat kod.

    Bagaimana untuk mendapatkan kod pengesahan

    Jika anda telah membolehkan Pengesahan log masuk, anda akan menerima mesej SMS dengan kod log masuk setiap kali anda memerlukannya. Jika anda menggunakan aplikasi Android, anda boleh memuat turun program Penjana Kod.

    Adakah saya perlu memasukkan kod setiap kali saya log masuk?

    Selepas memasukkan kod keselamatan dan log masuk, anda perlu memberikan nama kod pada komputer atau telefon anda dan menyimpannya (jika anda memerlukan peranti itu). Jika anda terus menerima gesaan kod apabila anda log masuk menggunakan salah satu peranti (rasmi) anda yang disimpan, anda mungkin perlu melaraskan tetapan penyemak imbas anda.

    Jika anda menggunakan fungsi pengesahan log masuk, sistem mesti menyimpan data komputer dan penyemak imbas anda supaya ia boleh dikenali apabila anda log masuk seterusnya.

    Sesetengah ciri penyemak imbas tidak membenarkan ini. Jika anda menggunakan ciri penyemakan imbas peribadi atau penyemak imbas anda dikonfigurasikan untuk mengosongkan sejarah penyemakan imbas anda apabila ditutup.