Могу ли я использовать empty () для неопределенной переменной? - PullRequest
0 голосов
/ 13 декабря 2018

index.php:

if(isset($_SESSION['user_id'])){
  $user_id = $_SESSION['user_id'];
}
###$_SESSION['user_id'] is = to $user['user_id'] that i get from database in a select query on login.php

Как вы можете видеть выше, я устанавливаю переменную $user_id только тогда, когда пользователь входит в систему. Я использую if(empty($user_id)){} для создания некоторых условий, и она работает хорошо, но мне любопытно, потому что, если пользователь не вошел в систему, $user_id будет неопределенной переменной, я новичок в php, поэтому я хочу знать, правильно ли я это делаю.

На странице, которую пользователь не должен просматривать, пока он не вошел в систему, я добавил этот код:

if(empty($user_id)) {
  $_SESSION['message'] = "You need to loge in to view this page";
  header("location: verify/error.php");
  exit;    
}

И для отображения некоторого содержимого, связанного с пользователем, я использую этот код:

if(!empty($user_id)){
   echo 'content related to the user, divs...etc';
}

У меня есть два вопроса:

1 - я делаю это правильно?

2 - Должен ли я изменить свой код на:

if(isset($_SESSION['user_id'])){
  $user_id = $_SESSION['user_id'];
}else{
  $user_id = '';
}

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Правильно ли я делаю это?

Прежде всего, мой ответ не будет описывать реализацию использования empty() в вашем случае противнеопределенные переменные предупреждения.Этот ответ состоит в том, чтобы дать вам направление и показать вам немного ООП для вашего случая и почему это эффективно.

Возьмем, к примеру, страницу A, не требующую аутентификации пользователя для доступа на чтение, ностраница B делает.

Вместо того, чтобы переписывать эту проверку последовательно во всем приложении для страницы 'n', мы можем написать структуру класса, которая сделает это за вас в зависимости от области доступа.

Давайте начнем с того, что приложение узнает, когда запретить чтение, создав интерфейс.В конечном итоге это будет использоваться для расширения класса аутентификации пользователя всякий раз, когда мы хотим отменить доступ на чтение, когда пользователь не вошел в систему.

namespace Application\Auth;

interface MustBeLoggedIn
{
}

Далее мы можем продолжить и построить класс аутентификации.Это то, что содержит директиву о том, как или в каком порядке этот класс будет выполнять свои методы в зависимости от типа его экземпляра.

namespace Application\Auth;

class Authenticable {

    protected $_user_id;
    private $_csrf = 'user_id';

    public function __construct()
    {
        # PHP 7+
        $this->_user_id = $_SESSION[$this->_csrf] ?? '';

        # PHP < 5.6
        # $this->user_id = isset($_SESSION[$this->_csrf]) ? $_SESSION[$this->csrf] : '';

        if($this instanceof MustBeLoggedIn)
            $this->mustBeLoggedIn();
    }

    private function mustBeLoggedIn()
    {
        if(!isset($this->_user_id))
            $this->authError();
    }

    protected function authError()
    {
        exit();
    }

    protected function isLoggedIn()
    {
        return isset($this->_user_id);
    }

}

Наконец, мы можем построить два пользовательских класса.Первый класс аннулирует доступ на чтение всем неавторизованным пользователям.

namespace Application\Auth;

class User extends Authenticable implements MustBeLoggedIn
{
    public function doSomething()
    {
        if($this->isLoggedIn())
            echo $this->_user_id;
    }

    protected function authError()
    {
        $_SESSION['message'] = 'Oh snap! Looks like you need to be logged in to view this page.';
        header('Location: verify/error');
        exit();
    }
}

Второй класс позволит и гостям, и аутентифицированным пользователям иметь доступ на чтение.

namespace Application;

class User extends Authenticable
{
    public function doSomething()
    {
        if($this->isLoggedIn())
            echo $this->_user_id;

        if(!$this->isLoggedIn())
            echo 'Well, you can still view this page';
    }
}

Развертывание представления теперьлегко.Без необходимости постоянно повторно объявлять, существует ли значение, и решать, что делать, вы можете создать экземпляр в зависимости от того, что вам подходит.

Если мы хотим предоставить пользователю доступ для чтения, когда он вошел в систему или вышел из нее,мы можем использовать Application \ User.

class MyView extends \Application\User {
    public function sayHi() {
        echo $this->isLoggedIn() ? "Hi, {$this->user_id}!" : "Hi, Guest!";
    }
}

(new MyView())->sayHi();

Если мы хотим отозвать доступ для чтения неавторизованным пользователям, мы можем использовать Application \ Auth \ User.

class MyView extends \Application\Auth\User {
    public function sayHi() {
        echo "Hi, {$this->user_id}!";
    }
}

(new MyView())->sayHi(); # Guests will be redirected to error/verify

Я надеюсь показать вамэто может помочь вам понять немного больше о PHP.Также следует отметить, что вы, вероятно, уязвимы для CSRF-атак , потому что ID (предполагающий представление целого числа) чрезвычайно легко подделать.Возможно, посмотрите на с помощью веб-токена JSON и передайте в него идентификатор пользователя.

$_SESSION['csrf'] = \Firebase\JWT\JWT::encode(array('user_id' => 1), 'secret'); # An integer represented a base-64 encoding is going to stand out, perhaps store a generated unique token or something else in regards to identifying this user
$user = \Firebase\JWT\JWT::decode($_SESSION['csrf'], 'secret', array('HS256')); # $user['user_id'] would hold 1

Касаясь комментария Fyrye относительно эксплуатации в рамках использования JWT, самым большим моментом, который нужно забрать, является:HS256 охранного большинства вытекает из секрета. Что это значит? Это означает, что вы контролируете, насколько безопасно вы это делаете.Метод, который я использую, состоит в том, чтобы придумать безопасный пароль, но что-то связанное с JWT.

$secret = '_userAuthentication%App';

Затем, чтобы повысить безопасность, я хэширую пароль, прежде чем передать его в HS256 дляиспользование шифрования.

use \Firebase\JWT\JWT;

JWT::encode(array(
    'Data' => 'You want to secure from the user',
    'Integrity' => 'This STILL should not mean it is trusted data'
), password_hash($secret, PASSWORD_BCRYPT));

При декодировании JWT также важно помнить основы - никогда не доверять данным .Мы можем использовать блоки try catch finally, не считая, наконец, в этом случае, чтобы гарантировать, что мы получим верную информацию.

use \Firebase\JWT\JWT;

try {
    $csrf = JWT::decode($jwt, password_hash($secret, PASSWORD_BCRYPT), array('HS256'));
} catch (Exception $e) {
    // Data was invalid - Potential forge ?
}

Последнее замечание, если вы используете SSL - который этидней, а затем подпишите JWT с RSA.

0 голосов
/ 13 декабря 2018

Чтобы проверить, установлена ​​ли переменная, вы должны использовать isset(), чтобы проверить это.empty() также вернет true, если будет возвращено ложное значение.На странице документа следующие значения считаются ложными:

"" (пустая строка)

0 (0 в виде целого числа)

0.0 (0в виде числа с плавающей запятой)

"0" (0 в виде строки)

NULL

FALSE

array () (пустой массив)

Так что, если $user_id может иметь одно из этих значений (возможно, целое число 0), то вы можете получить неожиданный результат.Если $user_id никогда не будет одним из этих значений, вы можете проверить, установлено ли оно с помощью !empty() без проблем.

...