检查用户是否使用会话登录而不是数据库查询

时间:2013-06-06 08:51:15

标签: php mysql database session login

我想知道检查用户是否使用其会话登录网站而不是查询我的数据库是否更好。

如果数据库中存在他的ID,那么在每个用户的每个子页面上查询数据库(想想千位用户)是不是有点太多了?

在某些情况下(如ID必须至少长10位,姓氏必须存在且一个条件),检查存储在用户会话中的值是不是更好,更快且不那么数据库繁重网站操作员应该知道的字符串应该存在)。难道不能将其视为(99%)安全方式来检查用户是否合法登录?我已经读过PHP以编码方式保存会话内容,因此对于想要获取内容以模拟其他用户的人来说,它是不可读的。

6 个答案:

答案 0 :(得分:2)

我相信你的问题存在误解。会话和数据库扮演不同的角色,即使它们都是数据存储。会话是临时存储,而数据库是永久存储。数据保留在数据库中,直到您明确删除它,但会话具有到期日期。数据库和会话之间还存在另一个主要区别,它被称为session-id。 Session-id是将HTTP请求与服务器上的适当会话数据相关联的一种方法。会话ID通常作为cookie在Web服务器和浏览器之间来回传输。这是关于会话如何运作的典型场景:

  1. 浏览器的第一个请求已到达Web服务器。服务器上的软件处理传入的请求,并发现它不包含会话ID(因为它是第一个请求)。因此,为此请求创建了一个随机生成的唯一会话ID,并通过响应(无论它可能是什么)发送回客户端。还有一个在服务器上创建的存储与新创建的会话ID相关联。

  2. 用户要求同一服务器上的另一个页面。这次请求到达服务器时,它带有一个session-id,因此不会为该请求创建一个新的session-id,而是加载与之关联的数据。如果服务器上的软件更改了数据,则会在将响应发送回浏览器时将其存储回存储器。

  3. 从现在开始,每个发送到Web服务器的请求都会加载相同的会话数据。除非从服务器中删除会话数据或会话ID,否则此过程将继续。

  4. 在解释的场景中,会话用于保持与请求关联的数据。会话数据的主要功能之一是存储用户的凭证数据。这是另一个场景:

    1. 用户打开网站的第一页。为他创建会话ID并将其发送回他的浏览器。

    2. 用户进入登录页面并填写表格并按下提交按钮。

    3. 登录请求已到达服务器。用户名和密码相互检查,如果经过验证,会话数据中会提到此会话ID属于哪个用户。

    4. 从现在开始,到达服务器的每个请求都会加载包含此请求来自的会话数据,并且与数据库无关(除非您将数据库用作会话数据存储)。

    5. 此后期方案称为authentication,这意味着验证请求是否来自他们声称来自哪些人。在通常情况下,一旦用户被认证,就不需要再次对他进行认证(除非会话被破坏)。就身份验证而言,只有当您想要检查用户名和密码时,才有必要使用数据库。

      此外,还有一个名为authorization的场景。在这种情况下,你知道谁在问什么,唯一剩下的就是检查他是否被允许这样做。您知道是谁在询问,因为您在会话数据中加载了经过验证的凭据,并加载了传入请求的会话ID。授权可以分为两种类型。首先,您可以检查并查看是否允许用户执行请求的操作。其次,您可能希望进一步检查并查看是否允许用户对请求的数据执行请求的操作。第一种类型是名为ACL(访问控制列表)的库的目的,第二种类型通常在每个项目中单独实现。

      ACL是一个函数(简单地说),它接受请求者用户和请求的操作(称为resource)并返回一个布尔值,指示是否允许用户执行操作。确切地说,资源可以是复合的(如Files_DeleteFiles_Read)。 ACL功能需要指示谁可以做什么。大多数开发人员在对用户进行身份验证时从永久存储(如数据库)加载此数据,并将其存储在会话数据中以防止从数据库重新加载。这是可能的,因为ACL数据不是那么大,并且可以将其存储在会话中。因此,通常使用ACL进行授权也不需要数据库访问(在创建它们之后)。

      剩下的唯一讨论是当您想要检查请求者是否允许对请求的数据请求的操作时。通常在这里通过数据,我们指的是数据库的记录,通常,有很多。因此,将大量数据存储在数据库本身以外的任何地方都是不合逻辑的。而且由于它已经存在于数据库中,因此没有比SQL更适合查询谁可以在哪条记录上执行操作的工具。您需要访问数据库以验证用户请求的授权。但在所有其他情况下,会话数据就足够了。

      总之,在所有解释的场景中,只有一个需要数据库访问。其他人只能使用会话数据完成。

答案 1 :(得分:1)

检查用户是否通过会话登录是完全可以接受的,无论如何都是最常用的。在您的登录代码中,当用户成功对数据库进行身份验证时,您可以在会话中设置一个标志,表示该用户已登录。在后续页面中,您在显示受保护内容之前检查此标志。

// username and password match against the db
$_SESSION['user'] = array(
    'username' => 'xxx',
    'userId' => 'xxx',
    'loggedIn' => true;
);

检查他们是否已登录:

if(isset($_SESSION['user']) && $_SESSION['user']['loggedIn'])
{
    // good to show protected content
}

执行此操作并不一定意味着您必须将所有用户详细信息转储到会话中,您仍然可以对其进行实时查找。

答案 2 :(得分:0)

虽然从本地文件中获取会话数据可能会快一点,但使用数据库更有利于扩展。

想象一下,您可以使用负载均衡器将流量分离到Web服务器的多个实例。如果数据存储在数据库(或群集)中,则负载均衡器无需担心哪个Web服务器包含特定请求的会话数据。所有服务器都有它们。这使事情变得更容易。

顺便说一句,您可以使用session_set_save_handler()

在两种方法之间轻松切换

答案 3 :(得分:0)

如果您的目标只是检查用户是否已登录,并且99%的安全性(根据您)是否足够,那么您可以这样做。但是,如果没有从外部资源(或内部地图)加载,则无法提及姓氏检查,但这不太可能。)

通常,您不仅要检查用户是否已登录。您加载用户的配置文件,角色,权限等...您仍然必须为此打到数据库。在大多数情况下,最好在检查会话时加载用户并缓存页面请求的其余部分的信息,这样就不会经常访问数据库。

或者,在分布式环境中使用类似APC用户缓存存储或Memcache的东西。

答案 4 :(得分:0)

您的会话数据存储在服务器中,位于php.ini文件中由session.save_path定义的位置,或者在运行时使用session_save_path存储在服务器中的会话数据存储在序列化文本中如果他们有权访问服务器,则可由人读取。

为了让其他人劫持用户会话,他们需要知道session_id。您可以查看How unique is the php session id以获取有关会话ID唯一性的更多信息。

要回答原始问题,是的,最好使用会话变量进行测试,以确定用户是否已经过身份验证。这可以通过检查像isset($_SESSION['auth_id'])这样的会话变量的存在来完成。当用户注销以销毁会话数据时,请务必session_destroy()和session_regenerateid()`。

答案 5 :(得分:0)

当您执行登录时,您可以为会话分配一些值。

<?php
// this should go right at the top of all pages using the session
session_start();

// other code

// your login procedure
if (login_condition == true)
{
    $_SESSION['logged_in'] = true;
    // other session values you want to store
}

然后,在您的仅登录页面中,您可以执行此操作

<?php
session_start();

if ( ! isset($_SESSION['logged_in']))
{
    header("Location: /path/to/login.php\r\n");
    exit;
}

如评论中所述,如果您需要在会话期间删除用户,该怎么办?您仍然需要某种方法来检查数据库的会话。

当然,如果这不是一个问题,请使用与上述类似的东西:)