在 PHP 中管理会话的正确方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/964071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Correct way to manage sessions in PHP?
提问by daniel
I'm currently setting up an authentication system.
My current layout is to get his email from the $_POST, md5 his password, and check the database against his email and his password.
If it matches, I use session_start, and I start storing data in the $_SESSIONvariable, like so:
我目前正在设置身份验证系统。我目前的布局是从$_POST.md5获取他的电子邮件,他的密码,并根据他的电子邮件和密码检查数据库。如果匹配,我使用session_start,然后开始在$_SESSION变量中存储数据,如下所示:
$_SESSION['uid'] = $uid;
$_SESSION['first_name'] = $first_name;
And on every page of the website, I would preform a simple check of
在网站的每一页上,我都会进行简单的检查
isset($_SESSION['uid']);
if not, redirect to index page, if is, load the page.
如果不是,则重定向到索引页面,如果是,则加载页面。
Am I doing this correctly? Is this secure enough? How easy is it for someone to forge that data?
我这样做正确吗?这足够安全吗?有人伪造这些数据有多容易?
Someone told me that I should create a table, with the user's email, and his session-id and use that to manage things... I've become rather confused - how would this help?
有人告诉我,我应该用用户的电子邮件和他的会话 ID 创建一个表,并用它来管理事情......我变得相当困惑 - 这有什么帮助?
Could someone clarify this? What is the correct way to manage authentication with PHP sessions?
有人可以澄清这一点吗?使用 PHP 会话管理身份验证的正确方法是什么?
Thanks.
谢谢。
回答by jrharshath
Security update: as of 2017-10-23: The advice in this answer, while of historical significance, is completely insecure. One should never use md5 in hashing a password because it is so easily brute forced. See this answerabout how to use the built-in password_* api to hash and verify passwords.
安全更新:截至 2017 年 10 月 23 日:此答案中的建议虽然具有历史意义,但完全不安全。永远不要在散列密码时使用 md5,因为它很容易被暴力破解。请参阅有关如何使用内置 password_* api 散列和验证密码的答案。
I've dealt with login/authentication systems earlier, and I find several shortcomings in this method:
我之前处理过登录/身份验证系统,我发现这种方法有几个缺点:
- you "md5 his password, and check the database" -- this means that if a person has access to the database, he can make out who has the same passwords!
- 你“md5他的密码,然后检查数据库”——这意味着如果一个人可以访问数据库,他可以找出谁拥有相同的密码!
ADDENDUM (19 Sep 2015) *Look at this link. It explains all the basics, the approaches you could take, why you should take those approaches and also gives you sample PHP code. If it's too long to read, just go to the end, grab the code and get set!
附录(2015 年 9 月 19 日)*查看此链接。它解释了所有基础知识、您可以采用的方法、为什么应该采用这些方法,还为您提供了示例 PHP 代码。如果阅读时间太长,请直接到最后,抓紧代码并进行设置!
BETTER APPROACH: to store md5 of username+password+email+saltin the database, saltbeing random, and stored together with the user's record.
更好的方法:将 md5 存储username+password+email+salt在数据库中,salt是随机的,并与用户记录一起存储。
- using the 'uid' directly in the session variables can be very risky. Consider this: my friend is logged on from my browser, and he leaves for a leak. I quickly check which cookies are set in his browser, and decipher his 'uid'. Now I own him!
- 直接在会话变量中使用 'uid' 可能非常危险。考虑一下:我的朋友从我的浏览器登录,然后他离开了。我迅速检查他的浏览器中设置了哪些 cookie,并破译了他的“uid”。现在我拥有他!
BETTER APPROACH: to generate a random sessionid when the user logs in successfully, and store that session ID in the $_SESSION[]array. You will also need to associate the sessionid with his uid (using the database, or memcached). Advantages are:
更好的方法:在用户成功登录时生成一个随机的 sessionid,并将该 session ID 存储在$_SESSION[]数组中。您还需要将 sessionid 与他的 uid 相关联(使用数据库或 memcached)。优点是:
- You can even bind a sessionid to a particular IP so that the sessionid can't be abused even if it is captured
- You can invalidate an older sessionid if the user logs on from another location. So if my friend logs in from his own computer, the sessionid on my computer becomes invalid automatically.
- 您甚至可以将 sessionid 绑定到特定的 IP,这样即使 sessionid 被捕获也不会被滥用
- 如果用户从其他位置登录,您可以使旧的 sessionid 无效。所以如果我的朋友从他自己的电脑登录,我电脑上的 sessionid 会自动失效。
EDIT: I've always used cookies manually for my session handling stuff. This helps me integrate the javascript components of my web apps more easily. You may need the same in your apps, in the future.
编辑:我总是手动使用 cookie 来处理我的会话。这有助于我更轻松地集成 Web 应用程序的 javascript 组件。将来,您的应用程序中可能需要相同的内容。
回答by linead
There is nothing wrong with doing this
这样做没有错
isset($_SESSION['uid']);
The session data is not transmitted to the user, it's stored on the server (or wherever the session handler stores it). What is transmitted to the user is the session id which is just a random string generated by PHP, this can be stolen of course because it's sent to the user.
会话数据不会传输给用户,而是存储在服务器上(或会话处理程序存储它的任何地方)。传输给用户的是会话ID,它只是一个由PHP 生成的随机字符串,这当然可以被盗,因为它是发送给用户的。
It should be clearly noted that randomly storing a string in the database and the users session and then using that to identify the user does not make the session any more secure, if the attacker gets the session they are still going to have compromised the user.
应该清楚地注意到,在数据库和用户会话中随机存储一个字符串,然后使用它来识别用户并不会使会话更加安全,如果攻击者获得会话,他们仍然会危害用户。
What we're discussing now is session hiHymaning, you may be thinking that you can just store the IP address in the session and check that with the IP coming from the request and be done with it. However it's often not that simple, I got burned with this recently when on a large web application we were storing a hash of the User Agent + IP address in the session and then checking that they matched on each occasion, for 99% of the users this worked fine. However, we started getting calls in from people who were finding that they were continually being logged out with no explanation. We put logging on the session hiHymaning checks to see what was going on and found that these people would come in on one IP and their session would continue on another, this wasn't a hiHymaning attempt however it was to do with how their proxy server worked, as a result we amended our session hiHymaning code to ascertain the class of the IP addressand from there figure out the network portion of the IP address and store just those parts of the IP address, this is slightly less secure in that session hiHymaning could theoretically come from inside the same network but caused all our false positives to go away.
我们现在讨论的是会话劫持,您可能认为您可以将 IP 地址存储在会话中,并使用来自请求的 IP 进行检查并完成它。然而,这通常不是那么简单,我最近在一个大型 Web 应用程序中被这个问题所困扰,因为我们在会话中存储了用户代理 + IP 地址的哈希值,然后检查它们在每次情况下是否匹配,对于 99% 的用户这工作得很好。然而,我们开始接到一些人的电话,他们发现他们不断地被注销而没有任何解释。我们将登录会话劫持检查以查看发生了什么,发现这些人会进入一个 IP,而他们的会话将在另一个 IP 上继续,这不是劫持尝试,而是与他们的代理服务器的方式有关工作,IP 地址的类别,并从中找出IP 地址的网络部分并仅存储 IP 地址的那些部分,这稍微不那么安全,因为会话劫持理论上可能来自同一网络内部,但导致了我们所有的误报走开。
回答by BlackBeltScripting
I must add onto this. If you are doing the "MD5 the password, then check the database" method, this suggest that the password is stored in a single md5 hash. This is no longer a standard way of storing hashed passwords.
我必须补充这一点。如果您正在执行“MD5 密码,然后检查数据库”方法,这建议将密码存储在单个 md5 哈希中。这不再是存储散列密码的标准方式。
I found this link very informative: http://www.itnewb.com/tutorial/Encrypting-Passwords-with-PHP-for-Storage-Using-the-RSA-PBKDF2-Standard
我发现这个链接非常有用:http: //www.itnewb.com/tutorial/Encrypting-Passwords-with-PHP-for-Storage-Using-the-RSA-PBKDF2-Standard
回答by Rigobert Song
I am not 100% on this but I think that it is possible to forge the session if someone really wanted to!
我不是 100% 的,但我认为如果有人真的想伪造会话是可能的!
I think saving the session id in a table is the most secure way to do this.
我认为将会话 ID 保存在表中是最安全的方法。
I have looked into this a little recently but again I'm not sure, interested to hear whats best practice!
我最近对此进行了一些研究,但我又不确定,有兴趣了解最佳实践!
Here are a few resources to look at
这里有一些资源可供查看
http://www.sitepoint.com/article/php-security-blunders/
http://www.sitepoint.com/article/php-security-blunders/

