如何保护我的登录页面

How to secure my login page

本文关键字:我的 登录 保护 何保护      更新时间:2023-09-26

我有一个login.html网页,用户可以输入用户名和密码。当他点击提交时,我使用Javascript收集输入的值,然后对php文件进行Ajax POST调用,并发送用户名和密码。

我担心的是,这是一种发送用户名和密码的安全方式吗?如果不是,我如何确保从html文件向运行后端的php发送数据的事务安全?

php文件然后连接到MySql Db,并检查用户是否退出以及密码是否正确。如果是,它只是将有效文本发送回javascript函数的ajax调用。如果不是,我确定它是无效用户?

我对这种逻辑不太满意?有没有更好的方法来实现这个过程?由于我正在将我的代码投入生产,我希望尽可能地保护它。

下面的代码工作得很好,我只需要提示来保护它。

login.html

<div>
    <h3>Login information</h3>
    <input type="text" name="user" id="usrnm" placeholder="Username/Email">
    <input type="password" name="pswdlogin" id="pswdlogin" placeholder="Password">
    <input type="checkbox" name="keepmeloggedin" id="keepmeloggedin" value="1" data-mini="true">
    <input type="submit" data-inline="false" onclick="logmein()" value="Log in">
    <div id="loginstatus">    </div>
 </div>

logmein.js

function logmein() {
  var usrnm = document.getElementById("usrnm").value;
  var pswdlogin = document.getElementById("pswdlogin").value;
  $.post("http://xyz/mobile/php/logmein.php",
    {
      usrnm: usrnm,
      pswdlogin: pswdlogin
    },
    function(data, status) {
      if (data == 'Valid') {
        window.open("http://xyz/mobile/home.html?email=" + usrnm + "", "_parent");
      } else {
        alert(data);
        document.getElementById("loginstatus").innerHTML = data;
      }
    });
}

logmein.php

<?php
$usrnm_original = $_POST['usrnm'];
$pswdlogin_original = $_POST['pswdlogin'];
$con = mysqli_connect("localhost", "cSDEqLj", "4GFU7vT", "dbname", "3306");
if (mysqli_connect_errno())
    {
    echo "Failed to connect to MySQL: " . mysqli_connect_error();
    }
mysqli_select_db($con, "dbname");
$usrnm = mysqli_real_escape_string($con, $usrnm_original);
$pswdlogin = mysqli_real_escape_string($con, $pswdlogin_original);
$result = mysqli_query($con, "SELECT * FROM registration WHERE email = '" . $usrnm . "' AND password='" . $pswdlogin . "' ");
$rows = mysqli_num_rows($result);
if ($rows == 1)
    {
    echo "Valid";
    }
  else
    {
    echo "In Valid Credentials Entered";
    }
mysqli_close($con);
?>

这确实属于codereview.stackeexchange.com,但无论如何我都会试一试。

首先,我会在你的表单中添加一个csrf令牌来阻止这些类型的攻击。

//the most simple type of csrf token
if (!isset($_SESSION['token'])):
    $token = md5(uniqid(rand(), TRUE));
    $_SESSION['token'] = $token;
else:
    $token = $_SESSION['token'];
endif;

然后在您的表单中,包括一个隐藏的输入字段:

<input type="hidden" name="token" id="token" value="<?php echo $token; ?>"/>

然后在ajax中添加令牌。

var usrnm = $('#usrnm').val();
var pswdlogin = $('#pswdlogin').val();
var token = $('#token').val();
{
    usrnm: usrnm,
    pswdlogin: pswdlogin,
    token: token
}

然后在php中,让我们在直接访问该页面时停止未定义的索引错误。

$usrnm_original = isset($_POST['usrnm'])?$_POST['usrnm']:false;
$pswdlogin_original = isset($_POST['pswdlogin'])?$_POST['pswdlogin']:false;
$token = isset($_POST['token'])$_POST['token']:false;

然后我们需要检查传递的令牌是否与我们的令牌相同

if(!$_SESSION['token'] == $token):
    die('CSRF Attacks are not allowed.');
endif;

然后,在接受用户数据时,我们需要停止使用mysqli_query,即使使用mysqli_real_escape_string进行清理,也需要使用prepared语句。另外,程序风格的代码让我哭了,所以我们将改变它。此外,让我们返回一个带有状态和消息的数组,这样更容易处理错误和成功报告。

$ret = array();
$mysqli = new mysqli("localhost", "cSDEqLj", "4GFU7vT", "dbname");
if($sql = $mysqli->prepare('SELECT * FROM registration WHERE email = ? and password = ?')):
    $sql->bind_param('ss', $usrnm_original, $pswd_original);
    if($sql->execute()):
        $sql->fetch();
        if($sql->num_rows > 0):
            $ret['status'] = true;
            $ret['msg'] = 'You have successfully logged in! Redirecting you now';
        else:
            $ret['status'] = false;
            $ret['msg'] = 'The credentials supplied were incorrect. Please try again';
        endif;
    endif;
    $sql->close();
    return json_encode($ret);
endif;

现在我们需要修改你的帖子功能。

$.post("http://xyz/mobile/php/logmein.php",
{
  usrnm: usrnm,
  pswdlogin: pswdlogin,
  token:token
},
function(data) {
  if (data.status == true) {
    window.open("http://xyz/mobile/home.html?email=" + usrnm + "", "_parent");
  } else {
    alert(data.msg);
    $('#loginstatus').text(data.msg);
  }
}, 'json');

最后,也是最重要的一点是,您使用了一种纯文本密码方法,从安全角度来看,这毫无意义。这正是你被黑客攻击的方式。相反,您应该至少使用sha256哈希方法。更改密码在数据库中的存储方式以使用sha256,然后将其传递到SQL选择器中进行比较,例如:

$pswdlogin_original = isset($_POST['pswdlogin'])? hash('sha256', $_POST['pswdlogin']):false;

当保存在数据库中时,密码将看起来像fcec91509759ad995c2cd14bcb26b2720993faf61c29d379b270d442d92290eb

为了清楚起见,我的回答是,但事实上,你甚至不应该重新发明东西。有很多应用程序和框架已经花了无数的时间来保护其身份验证系统。我建议你研究一下所有这些,因为它们将有助于培养你的核心编程技能,并教授基本的OOP实践

  • Lararvel 4.x
  • Zend 2
  • Phalcon
  • Yi

希望这会有所帮助。

首先,如果你想要"顶级"安全,你应该使用具有有效证书的HTTPS,否则任何攻击者都可能创建中间人攻击并拦截你的数据(我想这是你主要关心的问题)。只在登录页面上执行HTTPS是没有意义的,因为同一个攻击者可能会在不知道密码的情况下进行会话劫持攻击并冒充其他用户。

请注意,使用AJAX或HTML表单没有区别,数据是以相同的方式通过有线发送的。

如果你不想花费更多的资源(通常HTTPS证书需要花钱),你可以走"不太好的路线":传递一个哈希版本的密码,但这也有其缺点(如果你不在服务器端进行哈希,那么密码就会变成哈希本身…)

正如建议的那样,不要试图重新发明轮子,尝试使用像Laravel这样的知名框架,或者像Slim或Silex这样的较小框架,将代码迁移到它们可能会更容易。

最后,你必须问问自己,如果某个用户访问了另一个帐户,最坏的情况是什么?如果你正在部署一个没有个人数据的琐碎应用程序,也许你目前的解决方案已经足够好了。另一方面,如果你正在处理敏感信息,你必须注意保护你的网站。

进一步阅读:

  • 关于会话劫持
  • 关于中间人
  • 存储密码"好方法"(TM)