如何保护我的登录页面

时间:2014-09-08 16:05:43

标签: javascript php jquery ajax html5

我有一个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);
?>

2 个答案:

答案 0 :(得分:8)

这真的属于codereview.stackexchange.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实践

希望这有用。

答案 1 :(得分:1)

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

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

如果您不想花费更多资源(通常是HTTPS cerficates需要花钱),您可以选择“不是那么好的路线”:pass a hashed version of the password,但这也有其缺点(如果您不这样做)在服务器端散列,然后密码成为散列本身......)

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

最后你必须问问自己,如果某个用户可以访问另一个帐户,最糟糕的情况是什么?如果您正在部署一个没有个人数据的简单应用程序,那么另一方面,如果您处理敏感信息,您当前的解决方案就足够了,您必须注意保护您的网站。

进一步阅读: