seanslari yordamida ilg'or foydalanuvchi autentifikatsiyalash

Foydalanuvchilarning 3 turi mavjud bo'lgan veb-saytni tashkil qilaman:

-those who are registered and are subscribed for current month
-those that are registered, but are not subscribed for current month
-users that are not registered (you cant be subscribed if you are not regitered)

Men ushbu 3 turdagi foydalanuvchilarni identifikatsiya qiluvchi va to'g'ri ishlaydigan kod yaratdim. Mening savolim shu, borishning yo'li bormi? Men ilgari shunga o'xshash narsani qilmaganman. Yoki mening yondashuvimni qayta tarbiyalashim kerakmi?

//login.php

//connect to database and see if a user and password combination exists. Store $exists=0 if not, and $exists=1 if it exists.
session_start();

$conn = new mysqli($hn,$un,$pw,$db);
if ($conn->connect_error){
    die($conn->connect_error);
}
$query = "SELECT COUNT(1) as 'exists',expiration_date FROM table WHERE email = ? AND password = ?;";
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $email, $password);

$email = $_POST["email"];
$password = hash("hashingalgorithm", "salt".$_POST["password"]."salthere");

$stmt->execute();
   /* Get the result */
$result = $stmt->get_result();
$num_of_rows = $result->num_rows;
$row = $result->fetch_assoc();
$exists = $row["exists"];
$expiration_date = $row["expiration_date"];

/* free results */
$stmt->free_result();

/* close statement */
$stmt->close();
$conn->close();

date_default_timezone_set('Europe/Berlin');


if ($exists==0){
    echo "Wrong email or password";
    $_SESSION['loginerror'] = 2;
    header('Location: https://www.homepage.com/login'); 
}else if ($exists){
    if (strtotime($expiration_date) < (strtotime("now"))){//logged in, but not subscribed
        session_destroy();
        session_start();
        $_SESSION["authenticated"] = true;
        header('Location: https://www.homepage.com');
    }else{//logged in and ready to go
        $_SESSION["authenticated"] = true;
        $_SESSION["email"] = $email;
        header('Location: https://www.homepage.com');
    }
}else{
    echo "An error with has occured.";
} 

So'ngra veb-saytimdagi har bir sahifada, ushbu kodni ishlatib, qanday foydalanuvchi menga tashrif buyurganligini ko'rish uchun

session_start();
if(isset($_SESSION["authenticated"]) && isset($_SESSION["email"])){ 
    $email = $_SESSION["email"];

    //connect to database and fetch expiration_date for a user with $email. Store it in $expiration_date

$conn = new mysqli($hn,$un,$pw,$db);
    if ($conn->connect_error){
        die($conn->connect_error);
    }
    $query = "SELECT expiration_date FROM table WHERE email = ?;";
    $stmt = $conn->prepare($query);
    $stmt->bind_param("s", $email);

    $email = $_SESSION["email"];
    $stmt->execute();
    /* Get the result */
    $result = $stmt->get_result();
    $num_of_rows = $result->num_rows;
    $row = $result->fetch_assoc();
    $expiration_date = $row["expiration_date"];
    /* free results */
    $stmt->free_result();
    /* close statement */
    $stmt->close();
    $conn->close();
    date_default_timezone_set('Europe/Berlin');

    if (strtotime($expiration_date) < (strtotime("now"))){//logged in, but not subscribed
        session_destroy();
        session_start();
        $_SESSION["authenticated"] = true;
        header('Location: https://www.homepage.com');
    }else{  //html for subsribed and registered user
    echo <<<_END
    //html here
    _END;
    }
}else if(isset($_SESSION["authenticated"]) && !isset($_SESSION["email"])){
       //user is logged in, but not subscribed;
        echo <<<_END
        //htmlhere
        _END;
}else{// user is not registered nor is subscribed
        echo <<<_END
        //htmlhere
        _END;
}

Kod ishlaydi, lekin foydalanuvchi ro'yxatga olinib, unga obuna bo'lganidan keyin har bir sahifada ma'lumotlar bazasiga kirish haqida tashvishlanaman. Men ro'yxatdan o'tish va obuna bo'lish uchun foydalanuvchilarni jazolayman. Ushbu turdagi muammolarni hal qilish uchun yaxshiroq va takomillashtirilgan usul bormi?

6
Ma'lumotlar bazasiga kirishni ko'rsatish uchun faqat ma'lumotlar bazasiga ulanganman. Haqiqiy amalga oshirishni ta'minlamadim, chunki men buni o'zimcha deb hisoblamadim
qo'shib qo'ydi muallif sanjihan, manba
Ok. Ma'lumotlar bazasiga kirishga ruxsat beraman.
qo'shib qo'ydi muallif sanjihan, manba
Aslida sizning savolingizni tushunmayapman. Kodingizdagi ma'lumotlar bazasiga qayerdasiz?
qo'shib qo'ydi muallif Lelio Faieta, manba
Ushbu savolga tegishli kodni yuborishingiz kerak. Veb-saytingizdan ba'zi kodlar yo'q
qo'shib qo'ydi muallif Lelio Faieta, manba
Ha, $ _SESSION-da bir nechta qiymatlarni sinab ko'ring, ammo ushbu qiymatlarni tekshirishdan oldin sessiya faolligini tekshiring. Seansni aniqlashni oldini olish uchun session_regenerate_id dan foydalanganingizga ishonch hosil qiling.
qo'shib qo'ydi muallif Anthony Rutledge, manba
Umid qilamanki siz yaxshi javob olasiz. Loyihangizga omad tilaymiz!
qo'shib qo'ydi muallif Anthony Rutledge, manba

7 javoblar

Bu erdagi yechim, obuna bo'lgan foydalanuvchilarni tekshirish (faqat veb-saytingizga kiradigan birinchi sahifada), ya'ni login.php ichida foydalanishingiz mumkin,

// ...your previous code
session_start();
// initialize session variables
$_SESSION['subscribe_date'] = $_SESSION['authenticated'] = false;
if ($exists == 0){
    echo "Wrong email or password";
    $_SESSION['loginerror'] = 2;
    header('Location: https://www.homepage.com/login'); 
} else if ($exists){
    $_SESSION["authenticated"] = true;
    if (strtotime($expiration_date) > (strtotime("now"))){ //logged in,& subscribed
        $_SESSION["email"] = $email;
        $_SESSION['subscribe_date'] = $expiration_date;
    } else {  //logged in and not subscribed, do nothin!
    }
    header('Location: https://www.homepage.com');
} else {
    echo "An error has occured.";
} 

So'ngra, har bir sahifada faqatgina har bir so'rovni bajarish o'rniga faqat $ _ SESSION ['subscribe_date'] kodini tekshirish kerak

if(!empty($_SESSION["subscribe_date"]) && strtotime($_SESSION["subscribe_date"]) > (strtotime("now"))) {
//html for subscribed and registered user
} else if (!empty($_SESSION["authenticated"])) {
//html for registered user
} else {
//html for unregistered user
}

Bundan tashqari, session_destroy (); ni har bir sahifaga chaqirish uchun juda ham yomon fikrni o'chirib qo'yganimni unutmang. Agar kerak bo'lsa, uning o'rniga sessiya o'zgaruvchilarini o'rnatishingiz mumkin. ya'ni unset ($ _ SESSION ["email"]); session_destroy (); faqat foydalanuvchi tizimdan chiqish vaqtida qo'ng'iroq qilishingiz kerak. session_destroy() uchun ogohlantirish bo'limiga qarang

2
qo'shib qo'ydi
Sizni to'xtatganingiz uchun tashakkur. Ushbu yondashuv mening ehtiyojlarimni qondiradimi, deb hisoblamayman, chunki obuna har oyda. Yangilangan bo'lsa, foydalanuvchi endi obuna emas. Obuna statusini yangilashning ba'zi kodlari bo'lishi kerak
qo'shib qo'ydi muallif sanjihan, manba
session_regenerate_id
qo'shib qo'ydi muallif Melinda, manba
@sanjihan ha. Kodni $ expiration_date dan foydalanish kodini yangiladim. Shunday qilib, har safar foydalanuvchi tizimga kirsa, texnik jihatdan yuqoridagi kod ishlashi kerak :)
qo'shib qo'ydi muallif Niket Pathak, manba

Men bo'lsam, ushbu kodlarni ajratish va tashqi sinflar/funktsiyalarga qaytarishim kerak edi. Ammo, sizning kodingizni kichik tweekslar haqida gapiradigan bo'lsak, men nima qilaman:

login.php -ni tanlang

//connect to database and see if a user and password combination exists. Store $exists=0 if not, and $exists=1 if it exists.
session_start();

$conn = new mysqli($hn,$un,$pw,$db);
if ($conn->connect_error){
    die($conn->connect_error);
}
$query = "SELECT COUNT(1) as 'exists',expiration_date FROM table WHERE email = ? AND password = ?;";
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $email, $password);

$email = $_POST["email"];
$password = hash("hashingalgorithm", "salt".$_POST["password"]."salthere");

$stmt->execute();
/* Get the result */
$result = $stmt->get_result();
$num_of_rows = $result->num_rows;
$row = $result->fetch_assoc();
$exists = $row["exists"];
$expiration_date = $row["expiration_date"];

/* free results */
$stmt->free_result();

/* close statement */
$stmt->close();
$conn->close();

date_default_timezone_set('Europe/Berlin');


if ($exists==0){
    //removed echo, you shouldn't output anything before headers
    $_SESSION['loginerror'] = 2;
    header('Location: https://www.homepage.com/login');
    //use exit after each header redirect
    exit;
}else if ($exists){
    //moved to the top to minimize code redundancy
    $_SESSION["authenticated"] = true;
    //it's good to have user identifier (e.g. email) accessible for all authenticated users
    $_SESSION["email"] = $email;
    if (strtotime($expiration_date) <= (strtotime("now"))){//logged in, but not subscribed
        //unset only subscribed sessions, do not destroy all sessions
        unset($_SESSION["subscribed"]);
        header('Location: https://www.homepage.com');
        exit;
    }else{
        //logged in with active subscribtion
        $_SESSION["subscribed"] = true;
        header('Location: https://www.homepage.com');
        exit;
    }
}else{
    echo "An error with has occured.";
} 

har bir sahifaga kod qo'shildi

session_start();
if(isset($_SESSION["authenticated"])){
    //merged if-statement for both subscribed and unsubscribed user
    $email = $_SESSION["email"];

    //connect to database and fetch expiration_date for a user with $email. Store it in $expiration_date

    $conn = new mysqli($hn,$un,$pw,$db);
    if ($conn->connect_error){
        die($conn->connect_error);
    }
    //check if subscribed user is still subscribed and unsubscribed user is still unsubscribed
    $query = "SELECT expiration_date FROM table WHERE email = ?;";
    $stmt = $conn->prepare($query);
    $stmt->bind_param("s", $email);

    $email = $_SESSION["email"];
    $stmt->execute();
    /* Get the result */
    $result = $stmt->get_result();
    $num_of_rows = $result->num_rows;
    $row = $result->fetch_assoc();
    $expiration_date = $row["expiration_date"];
    /* free results */
    $stmt->free_result();
    /* close statement */
    $stmt->close();
    $conn->close();
    date_default_timezone_set('Europe/Berlin');

    //I have separated expiration verification and template echoing
    //first - expiration verification
    if (strtotime($expiration_date) <= (strtotime("now")) && isset($_SESSION["subscribed"])){
        //had been subscribed a second ago, but now he's not
        unset($_SESSION["subscribed"]);
        header('Location: https://www.homepage.com');
        exit;
    }else if (strtotime($expiration_date) > (strtotime("now")) && !isset($_SESSION["subscribed"])){
        //had been unsubscribed, but renewed subscription in the meantime (maybe in another browser with this session still active)
        $_SESSION["subscribed"] = true;
        header('Location: https://www.homepage.com');
        exit;
    }

    //user successfully passed expiraton verification, maybe was few times redirected
    //second - template echoing
    if (isset($_SESSION["subscribed"])) {
       //user is logged in and subscribed;
        echo '';
    }else{
       //user is logged in, but not subscribed;
        echo '';
    }
}else{
   //user is not registered
    echo '';
}

Sizning kodingizdagi har bir o'zgarishdan oldin sharhlar mavjud. Men qilgan o'zgarishlarning qisqacha ro'yxati:

  • use exit; after each header redirect: php - Should I call exit() after calling Location: header?
  • do not echo output before headers
  • use 3 session verification variables for every authenticated user - authenticated, subscribed and email
  • do not destroy whole session if user is not subscribed, use unset instead
  • I have merged both authenticated users (subscribed and unsubscribed) into one if statement
  • I have separated expiration verification and output echoing in two subsequent steps
  • on every page I am checking if subscribed user is still subscribed (subscription can expire during his session) and if unsubscribed did not become subscribed in meantime (he can use two browsers with active sessions)

Men qiladigan boshqa kichik tweaks (har bir faylning yuqori qismida sana_default_timezone_set-ni ko'chiring va h.k.), lekin ular sizning savolingizning mavzusi emas.

1
qo'shib qo'ydi
@NiketPathak - foydalanuvchi boshqa brauzerda obuna bo'lsa $ _ SESSION ["subscribe_date"] bu sessiyada bo'sh bo'ladi.
qo'shib qo'ydi muallif shaggy, manba
O'ylaymanki, OP har bir sahifada so'rovlarni bajarishdan qochmoqchi bo'lib, foydalanuvchi turini tekshiradi. Bundan tashqari, buni qilish kerak emas, deb o'ylayman. Agar foydalanuvchining obunasi 1 soniyadan keyin tugagan bo'lsa, u holda bu yerda strtotime ($ _ SESSION ["subscribe_date"]>> (strtotime ("now")) va obuna bo'lgan foydalanuvchilar uchun oddiygina $ _SESSION ["subscribe_date"] ni belgilang, u darhol foydalanuvchilarni obuna bo'limiga yo'naltiradi. U erda siz hech qanday so'rovni talab qilmaysiz va kerak bo'lganda ishlaydi!
qo'shib qo'ydi muallif Niket Pathak, manba
ha, lekin agar u boshqa biriga obuna bo'lgan bo'lsa, nima uchun foydalanuvchi eski brauzerga qaytib keladi? Lekin, agar u bunday qarorga kelsa, har doim ushbu foydalanuvchi qayta kirishga (boshqa eski brauzerlarda) va agar obunani yangilashni boshlasalar
qo'shib qo'ydi muallif Niket Pathak, manba

Umumiy holda, foydalanuvchi birinchi marta kirganda, $ _ SESSION da ikki davlat bayroqlarini o'rnating:

 $_SESSION['loggedIn']   = true
 $_SESSION['subscribed'] = bool //true or false

Men faqat ro'yxatdan o'tgan foydalanuvchilarning login qilishi mumkin deb o'ylayman. Agar foydalanuvchi o'z holatini o'zgartiradigan biror narsa qilsa, mos ravishda $ _ SESSION ni yangilang.

Qaydlarni tekshirishdan oldin sessiya faolligini tekshirib ko'ring. Bundan tashqari, tizimni aniqlashni to'xtatish uchun session_regenerate_id dan foydalaning.

Haqiqatdan ham murakkab turlari ketma-ketlikda User ob'ektini saqlashi va $ _ SESSION da saqlashi mumkin. So'ngra har bir sahifa yukida User ob'ektining xususiyatlari marshaled (unserialized) bo'lishi mumkin va yangi User ob'ektini tanlang. U dunyoda siz (a) tizimga kirganmi yoki (b) obuna bo'lganligini tekshirish uchun User ob'ektining xususiyatlarini tekshirib ko'rasiz. User ob'ektining holati $ _ SESSION superglobal da faqatgina xavfsiz holatga ega emas.

PHP Manual: Object Serialization

Kitob: Ob'ektga yo'naltirilgan Fikrlash jarayoni (4-nashr) : 12-bobga qarang

1
qo'shib qo'ydi
Serileştirmenin qanday foydalanishni o'rganishim kerak.
qo'shib qo'ydi muallif Melinda, manba

Har bir sahifa yukida SQL so'rovlarini bajarishdan oldin joriy foydalanuvchi haqida ma'lumotni saqlash uchun PHP sessiyasi o'zgaruvchisidan foydalaning.

Misol uchun, foydalanuvchi tizimga kirganda foydalanuvchi identifikatorini sessiya o'zgaruvchisida ushbu foydalanuvchilar sessiyasiga saqlang:

$_SESSION['user_id'] = ;

Keyingi sahifada yuklash, ma'lumotlar bazasi so'rovini ishga tushirishdan oldin bu tizimga o'zgaruvchini tekshiring.

if ($_SESSION['user_id']) {
   //normal operations
} else {
   //Make your database call
}
1
qo'shib qo'ydi

PHP sessiya modeli sessiyani boshlash va keyinchalik $ _ SESSION qatorida saqlangan va sessiyada saqlangan seansga tegishli barcha ma'lumotlarni olib kelish imkonini beradi.

Har bir sahifaga kirishga olib keladigan ma'lumotlar bazasi chaqiruvlari haqida tashvishlanish to'g'ri. Sessiya ma'lumotlari cookie bilan o'rnatilishi yoki POST yoki get usulida qaytarib berilishi mumkin. Shunday qilib, siz PHP sessiyasi id muddati va sessiya muddati uchun mos usulni aniqlashingiz kerak.

$_SESSION['name'] = 'value';//Stores Session values to avoid database requests
...
session_id($sid);//sets the id of existing session
session_start();//retreive stored session data;

Keyinchalik sessiya muddati davomida yoki maxsus harakatlarda hech qanday ma'lumotlar bazasi so'roviga ega bo'lmagan holda foydalanilgani uchun ro'yxatdan o'tgan va ro'yxatdan o'tgan kabi bayroqlarni belgilashingiz mumkin:

  • Obuna bo'lgan - hech qanday harakat kutilmagan. Foydalanuvchining barcha taxminlarni qoniqtirdi.
  • Ro'yxatdan o'tgan - faqat obuna bo'lishi mumkin. Shunday qilib, obuna amallaridan so'ng, foydalanuvchi muhit obuna so'rogunga qadar ma'lumotlar bazasini saqlab turishi mumkin.
  • Ro'yxatdan o'tmagan - Faqatgina ro'yxatdan o'tishi mumkin. Saqlangan ma'lumotlar yo'q. Ma'lumotlar bazasi so'rovlari yo'q.

Kirish boshlanganda obuna bo'lgan va ro'yxatdan o'tgan bayroqlari autentifikatsiya o'tgunga qadar FALSE ga o'rnatiladi. Ya'ni, mening fikrim - ma'lumotlar bazasi sessiya uchun faqat uch marta chaqirilishi kerak: foydalanuvchining haqiqiyligini tasdiqlash, ro'yxatga olish yoki unga obuna bo'lish. Kod ko'rsatilgandek, siz POST orqali ma'lumotlarni uzatasiz. Kirish kodini saqlash uchun sid yashirin maydonini barcha shakllarga qo'shing. Ma'lumotlar bazasidan ma'lumotlar bazasidan SELECT barcha kerakli ma'lumotlarni (parol emas, albatta), foydalanuvchi bilan o'zaro muloqot qilish uchun foydali bo'lishi mumkin.

1
qo'shib qo'ydi

Mening tushunchamda sizda allaqachon ish kodi bor. Va siz so'ragan narsa - bu fikr. Autentifikatsiya qilish va obuna uchun ma'lumotlar bazasiga tekshirishning har bir sahifasida takroriylikni olib tashlashni xohlaysiz.

Menimcha, sessiyalardan qanday foydalanishni o'zgartirish kerak,

 $_session['email']       //email address of user 
 $_session['auth_type']   //holds authentication type
 $_session['auth_till']   //subscription expire date

Keyinchalik obuna tekshirish funksiyasini yaratishga imkon beradi. Ushbu funktsiya alohida faylga qo'yilishi mumkin, masalan: init.php. Bu erda sessiyani boshlash mexanizmini qo'yishimiz mumkin, shunda har qanday hollarda sessiyalar mavjud bo'ladi.

if(!isset($_SESSION)) 
    session_start();      //start session if not already started

// lets define global vars to hold authentication type of visitor
define("SUBSCRIBED",1); 
define("UN_SUBSCRIBED",2);
define("REGISTERED",3);
function checkSubscription():bool{
    $return = false;
    if(($_session['auth_type']==SUBSCRIBED)&&(strtotime($_session['auth_till']) < strtotime("now")))
        $return= true;
    return $return
}

Login.phpda sessiyalarning autentifikatsiya turini o'rnatishda xuddi shu usuldan foydalaning.

Endi boshqa har qanday sahifada obunani tekshirish uchun funktsiyani ishlatish mumkin

misol uchun:

<?php
// file: product.php
include_once("init.php");
if(!checkSubscription()){
   //subscription finished. do what you need to do. otherwise continue.
}

Sizning kodlaringiz uchun ko'plab yaxshilanishlar mavjud. Lekin bu sizning ehtiyojlaringizga javob berishi mumkin deb o'ylayman. Iltimos, yordamchi bo'lsangiz, iltimos, menga xabar bering. Iltimos, Feysbuk ga tashrif buyuring va u erda foydali kodlash mavjudligini bilib qo'ying.

1
qo'shib qo'ydi
Menimcha, $ _session ['auth_till'] - obuna bilan ishlashning kalitidir va men buni qo'llayman. Biroq, keyingi oyga obuna bo'lgan foydalanuvchi emas, PayPal yoki boshqa xizmat (IPN orqali). $ _session ['auth_till'] muayyan foydalanuvchini o'zgartirish kerak, unga imzo qo'ymasdan.
qo'shib qo'ydi muallif sanjihan, manba

login.php-da DB-dan allaqachon expiration_date ni olgan bo'lsangiz, uni session variable

$_SESSION['expiration_date'] = $row['expiration_date'];

va har bir sahifada JB so'rovini amalga oshirish o'rniga yuqorida ko'rsatilgan qiymatdan foydalanishingiz mumkin

if (isset($_SESSION['expiration_date']) && (strtotime($_SESSION['expiration_date']) < (strtotime("now") ))
1
qo'shib qo'ydi
PhP |BotsUz
PhP |BotsUz
93 ishtirokchilar

Phpni o'rganishni Hohlasangiz https://t.me/joinchat/AAAAAE-KRc5dd5tPMmGmWA A'zo bo'lin