【问题标题】:php script- Allow one session only at a timephp 脚本 - 一次只允许一个会话
【发布时间】:2012-12-02 11:08:19
【问题描述】:

请帮助我一次只验证一个会话,请参阅下面的脚本,该脚本当前允许相同的用户名登录任意数量的会话。

我不确定何时何地验证会话,请帮助我只添加可以验证用户名会话的那几行。

<?php // accesscontrol.php
include_once 'common.php';
include_once 'db.php';

session_start();

$uid = isset($_POST['uid']) ? $_POST['uid'] : $_SESSION['uid'];
$pwd = isset($_POST['pwd']) ? $_POST['pwd'] : $_SESSION['pwd'];

if(!isset($uid)) {
  ?>
  <!DOCTYPE html PUBLIC "-//W3C/DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
<title>Login</title>
<meta http-equiv="Content-Type"
  content="text/html; charset=iso-8859-1" />
<head>
<style type="text/css">
<!--
.style1 {
    font-size: 16px;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
.style3 {
    font-size: 12px;
    font-family: Verdana, Arial, Helvetica, sans-serif;
}

body {
background-color: #D7F0FF;
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
}

-->
</style>

  </head>
<body>
  <h1 class="style1"> <br><br>Amogh Site - Login Required </h1>
  <span class="style3"><br>
  You <strong>must login to access this area </strong>of the site. <br>
  <br>
  If you are not a registered user, please contact your Admin
     to sign up for instant access!</span>
  <p><form method="post" action="<?=$_SERVER['PHP_SELF']?>">

<span class="style3">User ID:&nbsp;&nbsp;&nbsp;&nbsp;    
<input type="text" name="uid" size="12" />
<br>
<br />
Password:</span>    
<input type="password" name="pwd" SIZE="12" />
<br>
<br />
<input type="submit" value="Login" />
  </form></p>

</body>
  </html>
  <?php
  exit;
}

$_SESSION['uid'] = $uid;
$_SESSION['pwd'] = $pwd;

dbConnect("hitek_svga3");
$sql = "SELECT * FROM user WHERE
    userid = '$uid' AND password = '$pwd'";
$result = mysql_query($sql);
if (!$result) {
error('A database error occurred while checking your '.
    'login details.\\nIf this error persists, please '.
    'contact you@example.com.');
}

if (mysql_num_rows($result) == 0) {
  unset($_SESSION['uid']);
  unset($_SESSION['pwd']);
  ?>

  <!DOCTYPE html PUBLIC "-//W3C/DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title> Access Denied </title>
    <meta http-equiv="Content-Type"
      content="text/html; charset=iso-8859-1" />
    <style type="text/css">
<!--
.style1 {
    font-size: 16px;
    font-family: Verdana, Arial, Helvetica, sans-serif;
}
.style3 {
font-size: 12px;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
-->
</style>  

  </head>
  <body>
  <br/>
  <br/>

  <h1 class="style1"> Access Denied </h1>
  <p class="style3">Your user ID or password is incorrect, or you are not a
 registered user on this site. To try logging in again, click
 <a href="<?=$_SERVER['PHP_SELF']?>">here</a>. To access, please contact our Admin     !</a>.</p>
  </body>
  </html>
  <?php
  exit;
}

$username = mysql_result($result,0,'fullname');
$_SESSION['user'] = mysql_result($result,0,'userid');
$_SESSION['email'] = mysql_result($result,0,'email');
$_SESSION['notes'] = mysql_result($result,0,'notes');

?>

【问题讨论】:

  • 您的脚本似乎容易受到SQL injections 的攻击。看看Best way to prevent SQL injection?
  • 由于 HTTP 是无状态的,因此很难确定用户的会话是否已过期,从而确定新的登录尝试是新会话还是现有会话的副本。
  • @eggyal 然后可以简单地删除任何以前的会话并每次创建一个新会话。
  • @ose:是的。也许我误解了这个问题,因为我的阅读意图是拒绝进一步的登录尝试,而不是退出现有会话。
  • 顺便说一句,作为一般建议,在发布代码时删除公司名称等可识别信息是明智的。您永远不知道谁会在以后发现此代码,并推测您很容易受到特定风格的 SQL 注入攻击并侵入您的系统...

标签: php mysql session login


【解决方案1】:

首先,为什么要将密码存储在会话变量中?

其次,如果 POST 变量 'uid' 和 'pwd' 不存在,您的代码假定会话变量 'uid' 和 'pwd' 将存在,因此您需要确保其中一个或存在于您之前允许您的脚本继续。这必须在 session_start() 函数之后完成:

<?php // accesscontrol.php
include_once 'common.php';
include_once 'db.php';

session_start();

if(
      (!isset($_SESSION['uid']) || !isset($_SESSION['pwd'])) &&
      (!isset($_POST['uid']) || !isset($_POST['pwd']))
{
     //Redirect or throw exception or whatever
}

$uid = isset($_POST['uid']) ? $_POST['uid'] : $_SESSION['uid'];
$pwd = isset($_POST['pwd']) ? $_POST['pwd'] : $_SESSION['pwd'];

【讨论】:

  • 检查条件后我应该重定向到哪里,不是很清楚,请帮助
  • 我已经在脚本中添加了这个,但它仍然允许多个用户使用相同的用户 ID 登录。还有一点需要注意的是,这个脚本只在本地服务器上运行,而不是在互联网上运行,因此不存在 mysql 注入或任何此类问题。
【解决方案2】:

你不应该:

  • 在数据库中保留明文密码
  • 使用mysql 扩展
  • 2012 年无框架开发

问题的重点是:PHP 如何判断请求来自哪个用户?上次我检查它使用作为 GET 参数发送的 token 或 HTTP 请求标头部分中的 cookie(我认为它被称为 PHPSESSID)。

显然,为了保证没有人窃取会话,身份令牌必须通过安全通道进行交换,即一旦用户登录,您必须生成会话 ID 并禁用端口 80 上的普通 HTTP 套接字。需要登录用户的脚本必须保存在一个单独的主机中,该主机只允许 HTTPS 在端口 443 上。

会话 ID 将从登录脚本中分配,并保存在 user 表的列中。顺便说一句,常规应用程序使用单独的表将会话与用户相关联,但由于您需要每个用户一个客户端,user 表中的一列就足够了。

因此,当请求带有会话令牌时,如果令牌仍然有效,您的授权 逻辑将检查用户表。它应该使用令牌来验证用户,因此如果请求不包含令牌或在数据库中找不到令牌,则发出403 FORBIDDEN 并在@ 中建议登录 URL 987654328@ 标头 - 如果代理不自动遵循重定向,您还可以编写带有 &lt;a&gt; 链接的 HTML 页面。

登录脚本承诺使用令牌更新列,具体取决于您要执行的操作:使旧会话无效或阻止创建新会话,直到用户明确退出另一个客户端(后者会导致麻烦)如果用户无法访问他之前登录的旧机器,可能是因为移动设备关闭或因为它位于不同的建筑物中)

【讨论】:

  • 有没有演示这个例子的链接,请分享。
  • @user1114409 我没有任何链接,这不是一个原创的想法,它就是它的工作原理。在安全领域,通常有一个问题一个解决方案的方法。只需下载 Wordpress(或 Drupal 或 Joomla,或 Cake 或 Zend)并查看身份验证和授权例程。
  • @user1114409 看看CakeSessionDatabaseSession
  • 旧答案,但我不同意“你不应该”“在没有框架的情况下在 2012 年开发”这句话。我的意思是,学习过程呢?您是否在不知道您乘坐的车辆的情况下开始骑行?话虽如此,下午好:-)
  • 你从最糟糕的框架中学到的东西比从你自己身上学到的更多
猜你喜欢
  • 2015-03-12
  • 2023-03-28
  • 2012-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-26
  • 2019-10-12
相关资源
最近更新 更多