javascript 如何保护我的登录页面
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25728437/
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
How to secure my login page
提问by user3846091
I have a login.html webpage that lets user enter his username and password. When he clicks on submit I collect the entered value using Javascript and then make a Ajax POST Call to the php file and send the username and password.
我有一个 login.html 网页,可以让用户输入他的用户名和密码。当他点击提交时,我使用 Javascript 收集输入的值,然后对 php 文件进行 Ajax POST 调用并发送用户名和密码。
My concern here is that is this a safe way of sending username and password ? If not how can i secure this transaction of sending data from html file to php running the backend?
我在这里担心的是,这是发送用户名和密码的安全方式吗?如果不是,我如何才能确保将数据从 html 文件发送到运行后端的 php 的事务?
The php file then connects to the MySql Db and checks if the user exits and if the password is correct If Yes it simply sends a Valid text back to the ajax calls to the javascript function if not I determine it is an invalid user ?
php 文件然后连接到 MySql Db 并检查用户是否退出以及密码是否正确如果是,它只是将一个有效文本发送回对 javascript 函数的 ajax 调用,如果不是我确定它是一个无效用户?
I am not quite happy with this logic ? Is there a better way to implement this process ? Since i am putting my code to production I want to secure it as much as possible.
我对这个逻辑不太满意?有没有更好的方法来实现这个过程?由于我将代码投入生产,因此我希望尽可能保护它。
The below code works fine i just need tips to secure it.
下面的代码工作正常,我只需要提示来保护它。
login.html
登录.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);
?>
回答by Ohgodwhy
This really belongs on codereview.stackexchange.com, but I'll give it a shot anyway.
这确实属于 codereview.stackexchange.com,但无论如何我都会试一试。
Firstly, I'd add a csrf token to your form to stop those types of attacks.
首先,我会在您的表单中添加一个 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;
Then in your form, include a hidden input field:
然后在您的表单中,包含一个隐藏的输入字段:
<input type="hidden" name="token" id="token" value="<?php echo $token; ?>"/>
Then in your ajax, add the token.
然后在您的 ajax 中,添加令牌。
var usrnm = $('#usrnm').val();
var pswdlogin = $('#pswdlogin').val();
var token = $('#token').val();
{
usrnm: usrnm,
pswdlogin: pswdlogin,
token: token
}
Then in your php, let's stop the undefined index errors on access of that page directly.
然后在您的 php 中,让我们直接停止访问该页面时出现的未定义索引错误。
$usrnm_original = isset($_POST['usrnm'])?$_POST['usrnm']:false;
$pswdlogin_original = isset($_POST['pswdlogin'])?$_POST['pswdlogin']:false;
$token = isset($_POST['token'])$_POST['token']:false;
Then we need to check if the token that was passed is the same as our token
然后我们需要检查传递过来的token是否和我们的token一样
if(!$_SESSION['token'] == $token):
die('CSRF Attacks are not allowed.');
endif;
Then we need to stop using mysqli_query
when accepting user data, even if sanitizing with mysqli_real_escape_string
and instead use prepared
statements. Also, procedural style code makes me cry, so we'll be changing that. Furthermore, let's return an array with a status and a message, so it's easier to handle the error and success reporting.
然后我们需要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;
Now we need to modify your post function.
现在我们需要修改你的 post 函数。
$.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');
Finally, and most importantly, you have a plain text method of passwords being used, which makes no sense from a security perspective. This is precisely how you get hacked. Instead, you should be using at least the sha256
hashing method. Change how the passwords are stored in the database to use sha256
then make a comparison by passing that into the SQL selector, example:
最后,也是最重要的是,您使用的是纯文本密码方法,这从安全角度来看毫无意义。这正是您被黑客入侵的方式。相反,您应该至少使用sha256
散列方法。更改密码在数据库中的存储方式,sha256
然后通过将其传递到 SQL 选择器来进行比较,例如:
$pswdlogin_original = isset($_POST['pswdlogin'])? hash('sha256', $_POST['pswdlogin']):false;
And when saved in the database, the password will look like fcec91509759ad995c2cd14bcb26b2720993faf61c29d379b270d442d92290eb
for instance.
当保存在数据库中时,密码将看起来像fcec91509759ad995c2cd14bcb26b2720993faf61c29d379b270d442d92290eb
例如。
My answer has been for clarity sake, but in reality, you shouldn't even be reinventing things. There's plenty of applications and framework's out there that have placed countless hours into securing their authentication systems. I would recommend having a look into all of these, as they'll help build your core programming skills and teach fundamental OOP practices
我的回答是为了清楚起见,但实际上,您甚至不应该重新发明事物。有大量的应用程序和框架已经投入了无数个小时来保护他们的身份验证系统。我建议查看所有这些,因为它们将帮助您建立核心编程技能并教授基本的 OOP 实践
Hopefully this has been helpful.
希望这有帮助。
回答by mTorres
First of all, if you want "top" security you should use HTTPS with a valid certificate, otherwise any attacker may be able to create a Man in the middle attack and intercept your data (I guess this is your main concern). Doing the HTTPS on the login page only is meaningless as the same attacker could do a Session HiHymaning attack and impersonate other users without knowing the password.
首先,如果您想要“顶级”安全性,您应该使用带有有效证书的 HTTPS,否则任何攻击者都可以创建一个中间人攻击并拦截您的数据(我想这是您主要关心的问题)。仅在登录页面上执行 HTTPS 是没有意义的,因为同一攻击者可以进行会话劫持攻击并在不知道密码的情况下冒充其他用户。
Be aware that there is no difference of using AJAX or an HTML form, the data is sent though the wire in the same way.
请注意,使用 AJAX 或 HTML 表单没有区别,数据以相同的方式通过线路发送。
If you don't want to spent more resources (usually HTTPS cerficates costs money), you can go the "not that good route": pass a hashed version of the password, but this has its downsides too (if you don't hash at server side, then the password becomes the hash itself...)
如果您不想花费更多资源(通常 HTTPS 证书需要花钱),您可以走“不是那么好的路线”:传递密码的散列版本,但这也有其缺点(如果您不散列)在服务器端,然后密码成为哈希本身......)
As adviced, don't try to reinvent the wheel, try using a well known framework like Laravel, or one smaller like Slim or Silex, it might be easier to migrate your code to them.
按照建议,不要尝试重新发明轮子,尝试使用像 Laravel 这样的知名框架,或者像 Slim 或 Silex 这样更小的框架,将代码迁移到它们可能更容易。
At the end you must ask yourself, what is the worst case scenario if some user gets access to another account? If you're deploying a trivial app with no personal data, maybe your current solution is good enough on the other hand if you're dealing with sensitive information you must pay good attention securing your website.
最后,您必须问自己,如果某个用户可以访问另一个帐户,最坏的情况是什么?如果您正在部署一个没有个人数据的微不足道的应用程序,另一方面,如果您正在处理敏感信息,那么您当前的解决方案可能已经足够好了,您必须非常注意保护您的网站。
Further reading:
进一步阅读: