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

时间:2022-10-23 13:02:59

I'm wondering if it would be better to check if a user is logged into a website with his session instead of querying my database.

我在想,如果用会话检查用户是否登录了网站而不是查询我的数据库是否更好。

Isn't it a little bit too much to query the database on every subpage for every user (think of thousand of user) if his ID exists in the database?

如果每个用户的ID存在于数据库中,那么在每个子页面上查询每个用户的数据库(想想千万个用户)不是有点过分吗?

Wouldn't it be better, faster and not so database-heavy to just check the values stored in the user session, with some conditions (like the ID has to be at least 10 digits long, surname has to exist and a string which is just known by the website operater should exist). Couldn't that be seen as a (99%) safe way to check if a user is logged in legitimately? I've read that PHP saves the session content in an encoded way, so it is not readable for people who wants to grab the content in order to simulate another user.

如果只是检查用户会话中存储的值(比如ID必须至少有10位长、姓氏必须存在,以及网站操作人员刚刚知道的字符串),不是更好、更快、不那么数据库密集吗?这难道不能被视为检查用户是否合法登录的(99%)安全方法吗?我读到PHP以编码的方式保存会话内容,因此对于想要获取内容以模拟另一个用户的人来说,它是不可读的。

6 个解决方案

#1


2  

I believe there's a misunderstanding in your question. Sessions and databases play different roles, even though they are both data storage. The session is a temporary storage while the database is a permanent one. Data remain in the database until you remove it explicitly but sessions come with an expiration date. There's one another major difference between databases and sessions as well, and it's called session-id. Session-id is a mean to associate an HTTP request with the appropriate session data on the server. Session-ids usually are transferred back and forth between web servers and browsers as a cookie. Here's a typical scenario on how sessions work:

我相信你的问题有误解。会话和数据库扮演不同的角色,尽管它们都是数据存储。会话是临时存储,而数据库是永久存储。数据一直保存在数据库中,直到您显式地删除它,但是会话有一个过期日期。数据库和会话之间还有一个主要的区别,它叫做会话id。session -id是将HTTP请求与服务器上的适当会话数据相关联的一种方法。会话id通常作为cookie在web服务器和浏览器之间来回传输。这里有一个关于会话如何工作的典型场景:

  1. The very first request of a browser has arrived on a web server. The software on server processes the incoming request and sees that it includes no session-id (as it's the first request). So a randomly generated unique session-id is created for this request and sent back to the client with the response (whatever it might be). There's also a storage created on the server in association the newly created session-id.

    浏览器的第一个请求已经到达web服务器上。服务器上的软件处理传入的请求,并看到它不包含会话-id(因为它是第一个请求)。因此,为这个请求创建了一个随机生成的唯一的会话id,并将响应发送回客户机(不管它是什么)。在新创建的会话-id关联的服务器上还创建了一个存储。

  2. User asks for another page on the same server. This time when the request has arrived on the server, it comes with a session-id so instead of creating a new session-id for this request, the data associated with it is loaded. If the data is changed by the software on the server, it is stored back to the storage when is the response is sent back to the browser.

    用户请求同一服务器上的另一个页面。这一次,当请求到达服务器时,它带有会话-id,因此不会为该请求创建新的会话-id,而是加载与该请求相关的数据。如果服务器上的软件更改了数据,那么当响应发送回浏览器时,数据将被存储回存储区。

  3. From now on each request that is sent to web server loads the same session data. This process continues unless the session data or session-id is removed from the server.

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

In the scenario explained, sessions are used to keep data associated with requests. One of the major functions of session data is to store credential data of a user. Here's another scenario:

在解释的场景中,会话被用来保存与请求相关的数据。会话数据的主要功能之一是存储用户的凭据数据。这是另外一个场景:

  1. A user opens the first page of a website. A session-id is created for him and sent back to his browser.

    用户打开网站的第一页。为他创建一个会话id并发送回浏览器。

  2. User goes to the login page and fills in the form and presses the submit button.

    用户进入登录页面并填写表单并按submit按钮。

  3. The login request has arrived on the server. Username and password are checked against one another and if verified it is mentioned in the session data that this session-id belongs to which user.

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

  4. From now on, each request that is arrived on server loads the session data containing who this request comes from and it has nothing to do with the database (unless you use the database as session data storage).

    从现在开始,服务器上的每个请求都加载包含这个请求来自谁的会话数据,它与数据库没有任何关系(除非您将数据库用作会话数据存储)。

This late scenario is called authentication, which means verifying if the requests come from who they are claiming they are coming from. In ordinary cases, once a user is authenticated there's no need to authenticate him again (unless the session is destroyed). As far as authentication goes the only part database use is mandatory is when you want to check the username and password.

这个后期场景称为身份验证,这意味着验证请求是否来自他们声称来自的人。在通常情况下,一旦用户通过身份验证,就不需要再次验证他(除非会话被破坏)。就身份验证而言,数据库使用的惟一部分是必需的,即当您想要检查用户名和密码时。

Moreover, there's another scenario called authorization. In this scenario, you know who is asking what and the only thing that remains is to check if he is allowed to do it or not. You know who is asking because you have his validated credentials in session data loaded with incoming request's session-id. Authorization can be categorized into two types. First, you can check and see if the user is allowed to perform the requested action. Second, you may want to go further and check and see if the user is allowed to do the requested action on the requested data. The first type is the purpose of libraries called ACL (Access Control List) and second ones are usually implemented within each project individually.

此外,还有另一个场景称为授权。在这种情况下,你知道谁在问什么,剩下的唯一的事情就是检查他是否被允许这样做。您知道是谁在询问,因为在会话数据中有他的已验证的凭据,其中装载了传入请求的会话id。授权可以分为两种类型。首先,您可以检查并查看是否允许用户执行所请求的操作。其次,您可能需要进一步检查,看看是否允许用户对请求的数据执行请求的操作。第一种类型是称为ACL (Access Control List)的库的用途,第二种类型通常在每个项目中单独实现。

ACL is a function (to put it simply) which takes in the requester user and the requested action (called resource) and returns a boolean indicating if the user is allowed to do the action or not. To be precise, resources can be compound (like Files_Delete or Files_Read). The ACL function requires instruction on who can do what. Most developers load this data from a permanent storage (like a database) as the user is authenticated and store it in session data to prevent reloading it from the database. This is possible since ACL data is not that big and it is possible to store it in session. So usually authorizing using ACL requires no database access either (after they are created).

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

The only discussion left is for when you want to check if the requested action on the requested data is allowed for the requester. Usually here by data, we mean records of the database and usually, there are a lot of them. So it is illogical to store this huge amount of data anywhere other than the database itself. And since it is already in the database there's no tool more suitable better than SQL to query who can do what on which record. This is where you need to access database for verifying user request's authorization. But in all other scenarios session data is sufficient.

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

In conclusion, in all of the scenarios explained, there's only one that requires database access. Others can be done using session data only.

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

#2


1  

Checking if a user is logged in via the session is perfectly acceptable, and is how most do it anyway. In your login code, when the user successfully authenticates against the database, you can set a flag in the session to say that the user is logged in. On subsequent pages, you check this flag before showing protected content for example.

检查用户是否通过会话登录是完全可以接受的,而且大多数人都是这样做的。在登录代码中,当用户成功对数据库进行身份验证时,您可以在会话中设置一个标志,表示用户已登录。在随后的页面中,您在显示受保护内容之前检查这个标志。

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

Check if they're logged in:

检查他们是否登录:

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

Doing this does not necessarily mean you have to dump all user details into the session, you can still do live lookups for that.

这样做并不一定意味着您必须将所有用户细节都转储到会话中,您仍然可以进行实时查找。

#3


0  

If your objective is only to check that the user is logged in or not, and if that 99% safety (according to you) is adequate, then sure, you can do this. However, the surname check you mention is not possible without loading from an external resource (or an internal map, but that is unlikely).

如果你的目标只是检查用户是否登录了,如果99%的安全(根据你)是足够的,那么你可以这样做。但是,如果不从外部资源(或内部映射,则不可能进行姓检查)加载,则不可能进行姓检查。

Typically, you do more than just check if the user is logged in or not. You load the user's profile, roles, permissions, etc... You will have to hit the database anyway for this. In most cases, it is better to load the user while checking the session and cache the info for the rest of the page request so that you don't hit the database too often.

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

Or, use something like APC user cache store or Memcache in case of distributed environment.

或者,在分布式环境中使用APC用户缓存存储或Memcache。

#4


0  

Your session data is stored in the server at a location defined by session.save_path in the php.ini file or at run time using session_save_path the session data stored in the server is stored in a serialize text which is readable by human if they have access to the server.

会话数据存储在由会话定义的位置的服务器中。save_path php。ini文件或在运行时使用session_save_path将存储在服务器中的会话数据存储在序列化文本中,如果这些文本能够访问服务器,那么这些文本是可读的。

In order for someone else to hijack a users session they need to know the session_id. You can check How unique is the php session id for more information about the session id uniqueness.

为了让其他人劫持用户会话,他们需要知道session_id。您可以检查php会话id的惟一性,以获得关于会话id惟一性的更多信息。

To answer your original question, Yes it's best to use the session variable to test to see if the user has been authenticated or not. This can simply be done by checking an existence of a session variable like isset($_SESSION['auth_id']). Be sure to session_destroy() and session_regenerateid()` when the user logs out to destroy the session data.

要回答最初的问题,是的,最好使用会话变量来测试用户是否经过了身份验证。这可以通过检查会话变量isset($_SESSION['auth_id'])的存在来完成。当用户注销会话数据时,请确保session_destroy()和session_regenerateid()。

#5


0  

When you're performing the login you could assign some values to the session.

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

<?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
}

Then, in your login only pages you can do this

然后,在您的登录页面中,您可以这样做

<?php
session_start();

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

As mentioned in the comments, what if you need to delete the user while they're on the session? You will still need some way to check the session against the database.

正如评论中提到的,如果您需要在用户在会话期间删除他们,该怎么办?您仍然需要一些方法来对照数据库检查会话。

Of course if this is not a concern use something similar to the above :)

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

#6


0  

While fetching session data from a local file might be a little bit faster, using a database is better for scalability.

虽然从本地文件获取会话数据可能要快一些,但是使用数据库更好地实现可伸缩性。

Imagine a scenario where you use a load balancer to separate traffic to multiple instances of your web server. If data is stored in a database (or cluster) the load balancer doesn't need to work worry about which web server contains the session data for a certain request. All servers have them. This makes things much easier.

假设您使用负载均衡器将流量分离到web服务器的多个实例。如果数据存储在数据库(或集群)中,则负载均衡器不需要担心哪个web服务器包含某个请求的会话数据。所有服务器。这让事情变得容易得多。

Btw, you can easily switch between two methods using session_set_save_handler()

顺便说一句,您可以使用session_set_save_handler()在两个方法之间轻松切换

#1


2  

I believe there's a misunderstanding in your question. Sessions and databases play different roles, even though they are both data storage. The session is a temporary storage while the database is a permanent one. Data remain in the database until you remove it explicitly but sessions come with an expiration date. There's one another major difference between databases and sessions as well, and it's called session-id. Session-id is a mean to associate an HTTP request with the appropriate session data on the server. Session-ids usually are transferred back and forth between web servers and browsers as a cookie. Here's a typical scenario on how sessions work:

我相信你的问题有误解。会话和数据库扮演不同的角色,尽管它们都是数据存储。会话是临时存储,而数据库是永久存储。数据一直保存在数据库中,直到您显式地删除它,但是会话有一个过期日期。数据库和会话之间还有一个主要的区别,它叫做会话id。session -id是将HTTP请求与服务器上的适当会话数据相关联的一种方法。会话id通常作为cookie在web服务器和浏览器之间来回传输。这里有一个关于会话如何工作的典型场景:

  1. The very first request of a browser has arrived on a web server. The software on server processes the incoming request and sees that it includes no session-id (as it's the first request). So a randomly generated unique session-id is created for this request and sent back to the client with the response (whatever it might be). There's also a storage created on the server in association the newly created session-id.

    浏览器的第一个请求已经到达web服务器上。服务器上的软件处理传入的请求,并看到它不包含会话-id(因为它是第一个请求)。因此,为这个请求创建了一个随机生成的唯一的会话id,并将响应发送回客户机(不管它是什么)。在新创建的会话-id关联的服务器上还创建了一个存储。

  2. User asks for another page on the same server. This time when the request has arrived on the server, it comes with a session-id so instead of creating a new session-id for this request, the data associated with it is loaded. If the data is changed by the software on the server, it is stored back to the storage when is the response is sent back to the browser.

    用户请求同一服务器上的另一个页面。这一次,当请求到达服务器时,它带有会话-id,因此不会为该请求创建新的会话-id,而是加载与该请求相关的数据。如果服务器上的软件更改了数据,那么当响应发送回浏览器时,数据将被存储回存储区。

  3. From now on each request that is sent to web server loads the same session data. This process continues unless the session data or session-id is removed from the server.

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

In the scenario explained, sessions are used to keep data associated with requests. One of the major functions of session data is to store credential data of a user. Here's another scenario:

在解释的场景中,会话被用来保存与请求相关的数据。会话数据的主要功能之一是存储用户的凭据数据。这是另外一个场景:

  1. A user opens the first page of a website. A session-id is created for him and sent back to his browser.

    用户打开网站的第一页。为他创建一个会话id并发送回浏览器。

  2. User goes to the login page and fills in the form and presses the submit button.

    用户进入登录页面并填写表单并按submit按钮。

  3. The login request has arrived on the server. Username and password are checked against one another and if verified it is mentioned in the session data that this session-id belongs to which user.

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

  4. From now on, each request that is arrived on server loads the session data containing who this request comes from and it has nothing to do with the database (unless you use the database as session data storage).

    从现在开始,服务器上的每个请求都加载包含这个请求来自谁的会话数据,它与数据库没有任何关系(除非您将数据库用作会话数据存储)。

This late scenario is called authentication, which means verifying if the requests come from who they are claiming they are coming from. In ordinary cases, once a user is authenticated there's no need to authenticate him again (unless the session is destroyed). As far as authentication goes the only part database use is mandatory is when you want to check the username and password.

这个后期场景称为身份验证,这意味着验证请求是否来自他们声称来自的人。在通常情况下,一旦用户通过身份验证,就不需要再次验证他(除非会话被破坏)。就身份验证而言,数据库使用的惟一部分是必需的,即当您想要检查用户名和密码时。

Moreover, there's another scenario called authorization. In this scenario, you know who is asking what and the only thing that remains is to check if he is allowed to do it or not. You know who is asking because you have his validated credentials in session data loaded with incoming request's session-id. Authorization can be categorized into two types. First, you can check and see if the user is allowed to perform the requested action. Second, you may want to go further and check and see if the user is allowed to do the requested action on the requested data. The first type is the purpose of libraries called ACL (Access Control List) and second ones are usually implemented within each project individually.

此外,还有另一个场景称为授权。在这种情况下,你知道谁在问什么,剩下的唯一的事情就是检查他是否被允许这样做。您知道是谁在询问,因为在会话数据中有他的已验证的凭据,其中装载了传入请求的会话id。授权可以分为两种类型。首先,您可以检查并查看是否允许用户执行所请求的操作。其次,您可能需要进一步检查,看看是否允许用户对请求的数据执行请求的操作。第一种类型是称为ACL (Access Control List)的库的用途,第二种类型通常在每个项目中单独实现。

ACL is a function (to put it simply) which takes in the requester user and the requested action (called resource) and returns a boolean indicating if the user is allowed to do the action or not. To be precise, resources can be compound (like Files_Delete or Files_Read). The ACL function requires instruction on who can do what. Most developers load this data from a permanent storage (like a database) as the user is authenticated and store it in session data to prevent reloading it from the database. This is possible since ACL data is not that big and it is possible to store it in session. So usually authorizing using ACL requires no database access either (after they are created).

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

The only discussion left is for when you want to check if the requested action on the requested data is allowed for the requester. Usually here by data, we mean records of the database and usually, there are a lot of them. So it is illogical to store this huge amount of data anywhere other than the database itself. And since it is already in the database there's no tool more suitable better than SQL to query who can do what on which record. This is where you need to access database for verifying user request's authorization. But in all other scenarios session data is sufficient.

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

In conclusion, in all of the scenarios explained, there's only one that requires database access. Others can be done using session data only.

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

#2


1  

Checking if a user is logged in via the session is perfectly acceptable, and is how most do it anyway. In your login code, when the user successfully authenticates against the database, you can set a flag in the session to say that the user is logged in. On subsequent pages, you check this flag before showing protected content for example.

检查用户是否通过会话登录是完全可以接受的,而且大多数人都是这样做的。在登录代码中,当用户成功对数据库进行身份验证时,您可以在会话中设置一个标志,表示用户已登录。在随后的页面中,您在显示受保护内容之前检查这个标志。

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

Check if they're logged in:

检查他们是否登录:

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

Doing this does not necessarily mean you have to dump all user details into the session, you can still do live lookups for that.

这样做并不一定意味着您必须将所有用户细节都转储到会话中,您仍然可以进行实时查找。

#3


0  

If your objective is only to check that the user is logged in or not, and if that 99% safety (according to you) is adequate, then sure, you can do this. However, the surname check you mention is not possible without loading from an external resource (or an internal map, but that is unlikely).

如果你的目标只是检查用户是否登录了,如果99%的安全(根据你)是足够的,那么你可以这样做。但是,如果不从外部资源(或内部映射,则不可能进行姓检查)加载,则不可能进行姓检查。

Typically, you do more than just check if the user is logged in or not. You load the user's profile, roles, permissions, etc... You will have to hit the database anyway for this. In most cases, it is better to load the user while checking the session and cache the info for the rest of the page request so that you don't hit the database too often.

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

Or, use something like APC user cache store or Memcache in case of distributed environment.

或者,在分布式环境中使用APC用户缓存存储或Memcache。

#4


0  

Your session data is stored in the server at a location defined by session.save_path in the php.ini file or at run time using session_save_path the session data stored in the server is stored in a serialize text which is readable by human if they have access to the server.

会话数据存储在由会话定义的位置的服务器中。save_path php。ini文件或在运行时使用session_save_path将存储在服务器中的会话数据存储在序列化文本中,如果这些文本能够访问服务器,那么这些文本是可读的。

In order for someone else to hijack a users session they need to know the session_id. You can check How unique is the php session id for more information about the session id uniqueness.

为了让其他人劫持用户会话,他们需要知道session_id。您可以检查php会话id的惟一性,以获得关于会话id惟一性的更多信息。

To answer your original question, Yes it's best to use the session variable to test to see if the user has been authenticated or not. This can simply be done by checking an existence of a session variable like isset($_SESSION['auth_id']). Be sure to session_destroy() and session_regenerateid()` when the user logs out to destroy the session data.

要回答最初的问题,是的,最好使用会话变量来测试用户是否经过了身份验证。这可以通过检查会话变量isset($_SESSION['auth_id'])的存在来完成。当用户注销会话数据时,请确保session_destroy()和session_regenerateid()。

#5


0  

When you're performing the login you could assign some values to the session.

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

<?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
}

Then, in your login only pages you can do this

然后,在您的登录页面中,您可以这样做

<?php
session_start();

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

As mentioned in the comments, what if you need to delete the user while they're on the session? You will still need some way to check the session against the database.

正如评论中提到的,如果您需要在用户在会话期间删除他们,该怎么办?您仍然需要一些方法来对照数据库检查会话。

Of course if this is not a concern use something similar to the above :)

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

#6


0  

While fetching session data from a local file might be a little bit faster, using a database is better for scalability.

虽然从本地文件获取会话数据可能要快一些,但是使用数据库更好地实现可伸缩性。

Imagine a scenario where you use a load balancer to separate traffic to multiple instances of your web server. If data is stored in a database (or cluster) the load balancer doesn't need to work worry about which web server contains the session data for a certain request. All servers have them. This makes things much easier.

假设您使用负载均衡器将流量分离到web服务器的多个实例。如果数据存储在数据库(或集群)中,则负载均衡器不需要担心哪个web服务器包含某个请求的会话数据。所有服务器。这让事情变得容易得多。

Btw, you can easily switch between two methods using session_set_save_handler()

顺便说一句,您可以使用session_set_save_handler()在两个方法之间轻松切换