简体   繁体   English

使用会话ID验证用户身份-这样做安全吗?

[英]Use Session ID to verify user identity — safe to do so?

I am writing a shopping cart program from scratch using PHP (Zend) and MySQL. 我正在使用PHP(Zend)和MySQL从零开始编写购物车程序。 Now I am implementing the guest shopping cart and I save the items in cart into a table in my database. 现在,我实现了访客购物车,并将购物车中的项目保存到数据库中的表中。 Therefore each item in the table has the following fields: 因此,表中的每个项目都具有以下字段:

item_id session_id some_other_details_fields item_id session_id some_other_details_fields

When a user visits the website I assign a session ID using session_start(), and if he or she adds something into cart, I insert a row into the table above. 当用户访问网站时,我使用session_start()分配了会话ID,并且如果他或她在购物车中添加了一些内容,则会在上表中插入一行。

So when users want to edit or remove something from their cart, they can do: 因此,当用户想要编辑或删除购物车中的物品时,他们可以执行以下操作:

mydomain/cart/edit?item_id=XXX mydomain / cart / edit?item_id = XXX

and

mydomain/cart/delete?item_id=XXX mydomain / cart / delete?item_id = XXX

An obvious problem is that user can deliberately change XXX to access other's item info or remove items from other's cart. 一个明显的问题是用户可以故意更改XXX以访问其他人的商品信息或从其他人的购物车中删除商品。 So I am thinking of adding mydomain/cart/edit?item_id=XXX&sess_id=YYY to verify if the sess_id YYY matches the session_id of item XXX in database. 因此,我正在考虑添加mydomain / cart / edit?item_id = XXX&sess_id = YYY来验证sess_id YYY是否与数据库中项目XXX的session_id相匹配。

I don't know if this is a good practice, and if using session ID to verify user identity would be sufficient. 我不知道这是否是一个好习惯,是否使用会话ID验证用户身份是否足够。 Any idea or reference on this would be highly appreciated. 任何想法或参考,将不胜感激。

EDIT: 编辑:

  1. I would like to save the items in cart for as long as possible (eg, up to 1 year) , so I use session ID stored in cookies to identify users and save their items in cart in the database to make sure it will not be lost as long as the users do not clean up their cookies. 我想将商品尽可能长时间保存在购物车中(例如,最多1年) ,因此我使用存储在cookie中的会话ID来识别用户并将他们的商品保存在数据库中的购物车中,以确保不会只要用户不清理cookie就会丢失。 I was thinking sessions are usually used for storing user data for a shorter time, and may be less reliable than database, please let me know if this is wrong. 我当时以为会话通常用于较短时间地存储用户数据,并且可能不如数据库可靠,请告诉我这是否是错误的。

  2. For registered users I use a separate table for their carts and use user_id to identify them. 对于注册用户,我为他们的购物车使用单独的表格,并使用user_id进行标识。 If a guest registers I will move their items from the "guest cart table" to the "registered users cart table". 如果客人注册了,我会将他们的商品从“访客购物车表”移到“注册用户购物车表”。 Rather than using sessions which might be accidentally cleaned from time to time, I'd prefer to manually clean up the "guest cart table" just for peace of mind. 我宁愿使用手动清理“来宾推车表”来省心,也不愿使用可能会不时清理的会话。

  3. I am new in Zend so am not quite sure how to write this using Zend classes. 我是Zend的新手,所以不太确定如何使用Zend类编写此代码。 So I decided to use php for these stuff. 因此,我决定将php用于这些内容。

Please correct me if I the things I do above are stupid. 如果我上面做的事情很愚蠢,请纠正我。 :) :)

I can't fully understand your design. 我无法完全理解您的设计。 Using a database suggests permanent storage, but binding the cart to a session means that users cannot register and keep their carts. 使用数据库建议永久存储,但是将购物车绑定到会话意味着用户无法注册和保留他们的购物车。

  • If cart is just session data, it should get stored right into $_SESSION . 如果cart只是会话数据,则应将其直接存储在$_SESSION
  • If cart is permanent, the key should be the user_id . 如果cart是永久的,则密钥应为user_id
  • If you want a session cart that optionally gets saved into database when user registers, you can either use both approaches or go for database only. 如果要使会话购物车在用户注册时有选择地保存到数据库中,则可以使用两种方法,也可以仅用于数据库。 If you choose the latter, user_id would be optional and $_SESSION would contain cart_id . 如果选择后者,则user_id将是可选的,而$_SESSION将包含cart_id

Additionally, transmitting the session ID in the URL (the default behaviour in earlier PHP versions) proved to be a wrong idea: it's too easy to give away your session data inadvertently (eg by just sending a link to a friend). 此外,事实证明,在URL中传输会话ID(早期PHP版本中的默认行为)是一个错误的想法:很容易不经意地泄露会话数据(例如,仅向朋友发送链接)。

To sum up: there's normally no need to use the session ID. 总结一下:通常不需要使用会话ID。


I've just noticed your edit: 我刚刚注意到您的修改:

I would like to save the items in cart for as long as possible (eg, up to 1 year), so I use session ID stored in cookies to identify users and save their items in cart in the database to make sure it will not be lost as long as the users do not clean up their cookies. 我想将商品尽可能长时间保存在购物车中(例如,最多1年),因此我使用存储在cookie中的会话ID来识别用户并将他们的商品保存在数据库中的购物车中,以确保不会只要用户不清理cookie就会丢失。

So the shopping cart has actually nothing to do with the PHP session. 因此,购物车实际上与PHP会话无关。 Using the session ID as cart identifier unnecessarily links the whole session feature with your database cart and adds a lot of extra hassle for no benefit: 使用会话ID作为购物车标识符,不必要地将整个会话功能与数据库购物车链接起来,并且增加了很多麻烦,没有好处:

  • You need to change the default session settings so session cookies persists across browser restarts. 您需要更改默认会话设置,以便会话cookie在浏览器重新启动后仍然存在。

  • You increase the risk of session hijacking by reusing the same ID for months. 通过重复使用相同的ID数月,会增加会话劫持的风险。

Are you sure you don't really mean cookie rather than session ? 您确定您不是在说cookie而不是会话吗? It's just fine to generate a very long random alphanumeric identifier, store it into a cookie, and use it as secondary key for the database table. 生成一个非常长的随机字母数字标识符,将其存储在cookie中,并将其用作数据库表的辅助键是很好的。


Followup questions 后续问题

In terms of safety, would it be sufficient to generate just one long alphanumeric "GUID" for each guest and use that "GUID" to verify the identity when he or she comes back? 在安全方面,仅为每个客人生成一个长字母数字“ GUID”并在返回时使用该“ GUID”验证身份就足够了吗?

It doesn't need to global (the G in GUID) but I suppose it won't hurt. 它不需要全局(GUID中的G),但我想它不会受到伤害。 But you need to define "sufficient". 但是您需要定义“足够”。 Binding data to an IP address or User-Agent string makes it harder for attackers to gain access and makes it easier to user to lose his data. 将数据绑定到IP地址或User-Agent字符串使攻击者更难获得访问权限,并使用户更容易丢失数据。 Using HTTPS-only makes it more secure you need to use HTTPS everywhere. 仅使用HTTPS可以提高安全性,您需要在所有地方都使用HTTPS。

To avoid "GUID" conflicts, is there a good point to start? 为避免“ GUID”冲突,是否有一个好的起点? I used session ID just because it will generate a "GUID" for me. 我使用会话ID只是因为它将为我生成一个“ GUID”。

Sorry but the session ID is not a GUID: it's just a cryptographic hash with a random seed. 抱歉,会话ID不是GUID:它只是带有随机种子的加密哈希。 But please think about it: it's extremely difficult to win a lottery that sells numbers from 00000 to 99999 (that's 1/100000 chances). 但是请考虑一下:要赢得彩票,从00000到99999(即1/100000的机会)销售彩票,是极其困难的。 If you generate a 32-character string with digits and 26 English letters you have 1 / 36^32 = 1.5787740357426709877210×10 -50 . 如果您生成一个包含数字和26个英文字母的32个字符的字符串,则您有1/36 ^ 32 = 1.5787740357426709877210×10 -50

For my case when shall I use sessions (as a best practice)? 就我而言,我什么时候应该使用会话(作为最佳实践)? I'm kinda lost if this is not a good scenario to use sessions. 如果这不是使用会话的好方案,我有点迷茫。 Many thanks! 非常感谢!

You're possibly using sessions already for user sign-in or order payment, for a pretty good reason: since HTTP is a stateless protocol, there's no other way to do it. 您可能已经在使用会话进行用户登录或订单付款,原因非常充分:由于HTTP是无状态协议,因此没有其他方法可以使用。 Why is it so important to store the cart in session at any cost? 为什么在会话中不惜一切代价存储购物车如此重要? ;-) ;-)

Others told you to just use session, and generally this is the right way to do it. 其他人告诉您只使用会话,通常这是正确的方法。 However, if you want a dual system "you can make an account, but you're not forced to do so", I see why you'd want to use a database (a single cart-saving system for both types of users, with the permanence needed by the registered ones). 但是,如果您要使用双重系统“您可以创建一个帐户,但又不必这样做”,那么我明白了为什么要使用数据库(这两种类型的用户都可以使用一个购物车节省系统,以及已注册者所需的永久性)。

So, if I understood your intention right, you want purchases in a database, related to the user ID. 因此,如果我理解您的意图正确,那么您希望在与用户ID相关的数据库中进行购买。 However, when the user chooses not to register and/or log in, you have a problem. 但是,当用户选择注册和/或登录时,您会遇到问题。 In this case, I'd suggest saving some temporary user ID in a session, along with some flag (ie $_SESSION["realUser"] = false; ) and using it as if it were real. 在这种情况下,我建议在会话中保存一些临时用户ID以及一些标志(即$_SESSION["realUser"] = false; ),并以真实的方式使用它。 To avoid conflicts, those temporary names should be unique. 为避免冲突,这些临时名称应唯一。 For example, they can start with a space character, which I assume is not allowed for the regular user IDs. 例如,它们可以以空格字符开头,我认为常规用户ID不允许使用该字符。 Alternatively, you can use the pair of variables $userId, $realUser as a user identifier, and in that case $userId can be the same as the session ID. 或者,您可以使用变量对$userId, $realUser作为用户标识符,在这种情况下, $userId可以与会话ID相同。

However, carts connected to these temporary IDs will not last you a year. 但是,连接到这些临时ID的购物车将无法使用一年。 Once the session is deleted, the user will have no way to access that data. 一旦删除会话,用户将无法访问该数据。 So, this data can be pruned after a much shorter period of time, while the data related to the regular users doesn't have to be pruned at all (so, they can find their cart even after a decade, although doing so doesn't make much sense to me). 因此,可以在短得多的时间段内删除该数据,而根本不需要修剪与普通用户有关的数据(因此,即使十年后他们也可以找到他们的购物车,尽管这样做不会对我来说没有多大意义)。

If I understood you wrong and you don't want to mix registered users with the unregistered ones, just put all the data in the session and forget about databases for this, as others have suggested. 如果我理解您的理解是错误的,并且您不想将注册用户与未注册用户混合使用,只需将所有数据放入会话中,就可以像其他人所建议的那样忽略数据库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM