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 = '';
}
答案 0 :(得分:1)
要检查是否已设置变量,应使用getLocalizableSampleTemplateForComplication
进行测试。如果返回错误的值,isset()
也将返回empty()
。在文档页面中,以下值被视为false:
“”(空字符串)
0(0为整数)
0.0(浮点数为0)
“ 0”(0作为字符串)
NULL
假
array()(一个空数组)
因此,如果true
可以具有这些值之一(可能是整数0),则可能会得到意外的结果。如果$user_id
永远不是这些值之一,则可以检查是否使用$user_id
进行了设置。
答案 1 :(得分:1)
我做对了吗?
首先,我的答案将不会描述针对未定义的变量警告使用empty()
的实现。答案是为您提供指导,并向您展示一些针对您的情况的OOP以及为何有效。
举个例子,页面A不需要对用户进行身份验证才能进行读取访问,而页面B则需要进行身份验证。
我们可以在整个应用程序中始终为页面“ n”重新编写此检查,而不是重新编写此检查,而是根据访问范围来编写一个为您执行此检查的类结构。
首先,通过创建接口使应用程序知道何时禁止读取访问。每当我们要在用户未登录时撤销读取访问权限时,它将最终用于扩展User身份验证类。
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);
}
}
最后,我们可以构建两个User类。头等舱将撤销对任何未授权用户的读取访问权限。
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 attacks的攻击,因为ID(假设代表整数)非常容易伪造。也许看看using a JSON Web Token并将用户ID传递给它。
$_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(目前是必需的),请使用RSA签署JWT。