提交密码的最佳做法是什么? [英] What are the best practices for password submission?

查看:91
本文介绍了提交密码的最佳做法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个带有用户页面的网站.目前,它是通过以下方式设置的:

I am building a website with a user page. Currently it is set up in the following way:

用户在相应的字段中输入用户名和密码,然后按提交.

The user types their username and password into corresponding fields then the user pressed submit.

js代码使用纯文本的密码和用户名将get请求发送到php脚本.

The js code sends a get request to a php script with the password and username in plain text.

如果凭据正确,则php将随机生成的会话令牌返回到js代码,否则返回错误消息.

The php returns a randomly generated session token to the js code if the credentials are correct and an error message otherwise.

现在,用户在登录时进行的所有将来交互都将要求在任何get请求中提供会话令牌.然后,PHP将检查会话令牌是否正确.

All future interactions the user engages in while logged on will now require the session token to be provided in any get requests. The php will then check that the session token is correct.

在后端,用户名与盐和盐腌密码的哈希值(sha256)一起存储在数据库中. (盐是在创建帐户时随机生成的.)

In the back end, the user name is stored in a database along side a salt and the hash (sha256) of the salted password. (the salt is randomly generated upon account creation).

我的问题如下:上面的描述中是否有不安全的地方?如果是这样,应该怎么做.更广泛地讲,围绕网站设置用户登录页面或帐户系统的最佳实践是什么.谢谢

My question is as follows: Is there anything in the description above that seems insecure? If so, what should be done instead. More broadly, what are the best practices around setting up a user login page or account system for a website. Thanks

推荐答案

为什么要重新发明轮子.

Why are you trying to re-invent the wheel.

Php已经内置了密码加密功能,所以为什么要使用 Sha256 + Salt .

Php already has builting password encryption functions so why using Sha256 + Salt.

同样,它们是两种身份验证类型 1.)基于会话的登录 2.)基于令牌的登录.

Again they are two type of authentication 1.) Session Based Login 2.) Token Based Login.

在撰写本文时,您将会话登录与令牌登录结合在一起.您将需要决定要申请哪一个.

From your write-up you are combining session login with token login. You will need to decide which one that you want to apply.

因此,您需要了解许多php验证或清除功能,以确保代码更安全.

Consequently they are alot of php validation or sanitization functions that you need to know to keep your code more secured.

1.)使用strip_tags()

这将从表单输入或变量中删除所有html元素 例如

This will strips out all html elements from form inputs or variables Eg

$email = strip_tags($_POST['email']);

2.)使用htmlentities或htmlspecialchars防止XSS攻击.

这会将htmls标记转换为它们各自的实体.它仅在将结果打印或回显到html页面时使用 您将在welcome.php页面中看到我如何使用它 查看应用程序:

This converts htmls tags to their respective entities. its only used when printing or echoing result to html page to You will see how i used it in the welcome.php page See Applications:

$email = htmlentities($_POST['email']);

3.)对变量进行转义以防止sql注入攻击

如果使用的是Mysqli,则要使用的最佳sql方法是准备语句. 另外,您仍然可以使用 mysqli_real_escape_string()函数对变量进行转义 查看应用程序

If you are using Mysqli, the best sql method to be used is prepared Statement. Alternatively you can still escape variables using mysqli_real_escape_string() functions See Application

// escape variables Against sql injections
$email = mysqli_real_escape_string($conn, $_POST['email']);

4.)如果使用基于会话的登录,则需要使用 sessionId重新生成方法.这将有助于重新生成新会话 标识为用户登录名,从而防止会话固定攻击.不用担心,您将需要在下面的login.php代码中使用它 查看应用程序:

4.) If you are using session based login, You need to use sessionId regenerate method. This will help to regenerate new session Id as user login thus preventing session fixation attack. do not worry you will need how to use it in the login.php code below See Application:

// first you will need to initialize sessions
session_start();
session_regenerate_id();

这只是其他安全措施中的少数

This are just few among other security measures

让我们看看使用php密码验证功能的基于会话的登录

Lets have a look at Session based login using php password verify functions

假设这是您的

registration.php

<?php 
$conn = mysqli_connect("localhost","root","","demo");

if(!$conn){
    die("Connection error: " . mysqli_connect_error()); 
}

if(isset($_POST['submit'])){
        $firstName = mysqli_real_escape_string($conn,$_POST['first_name']);
        $surName = mysqli_real_escape_string($conn,$_POST['surname']);
        $email  = mysqli_real_escape_string($conn,$_POST['email']);
        $password = mysqli_real_escape_string($conn,$_POST['password']);

        $options = array("cost"=>4);
        $hashPassword = password_hash($password,PASSWORD_BCRYPT,$options);

        $sql = "insert into users (first_name, last_name,email, password) value('".$firstName."', '".$surName."', '".$email."','".$hashPassword."')";
        $result = mysqli_query($conn, $sql);
        if($result)
        {
            echo "Registration successfully";
        }
    }
?>

这就是您的 login.php 代码的样子

<?php 
$conn = mysqli_connect("localhost","root","","demo");

if(!$conn){
    die("Connection error: " . mysqli_connect_error()); 
}
if(isset($_POST['submit'])){
    $email = mysqli_real_escape_string($conn,$_POST['email']);
    $password = mysqli_real_escape_string($conn,$_POST['password']);

    $sql = "select * from users where email = '".$email."'";
    $rs = mysqli_query($conn,$sql);
    $numRows = mysqli_num_rows($rs);

    if($numRows  == 1){
        $row = mysqli_fetch_assoc($rs);
        if(password_verify($password,$row['password'])){
            echo "Password verified and ok";

// initialize session if things where ok.


session_start();
session_regenerate_id();

$_SESSION['surname'] = $row['surname'];
$_SESSION['first_name'] = $row['first_name'];
$_SESSION['email'] = $row['email'];

// take me to welcome.php page
header('Location: welcome.php');

        }
        else{
            echo "Wrong Password details";
        }
    }
    else{
        echo "User does not exist";
    }
}

?>

Welcome.php 现在看起来像下面的代码,以显示经过身份验证的用户的会话信息.

Welcome.php will now look like code below to show authenticated users session info.

//使用htmlentities或htmlspecialchars防止XSS攻击.

//use htmlentities or htmlspecialchars to prevent XSS Attack.

<?php echo htmlentities($_SESSION['surname'], ENT_QUOTES, "UTF-8"); ?>

<?php echo htmlspecialchars($_SESSION['first_name'], ENT_QUOTES, "UTF-8"); ?>
<?php echo htmlentities($_SESSION['email'], ENT_QUOTES, "UTF-8"); ?>

现在,在我看到的帖子中,您看到在哪里写了每个http请求发送一个生成的令牌的信息.在这种情况下,我想你是 尝试减轻 CSRF攻击.

Now in your post I Saw where you wrote sending a generated token with every http request. In this case I guess you are trying to mitigate CSRF Attack.

登录后,这是最好,最安全的操作方式

Here is the best and most secured way to do once you logged in

为防止CSRF,您需要验证一次令牌,该令牌已过POST,并与当前会话相关联. 类似以下内容. .

To prevent CSRF you'll want to validate a one-time token, POST'ed and associated with the current session. Something like the following . . .

在用户请求的页面上,例如,插入付款记录:

On the page where the user requests eg to insert a record for payments:

payment.php

<?php
 session_start();
 $token= md5(uniqid());
 $_SESSION['payment_token']= $token;
 session_write_close();
?>
<html>
<body>
<form method="post" action="payment_save.php">
 <input type="hidden" name="token" value="<?php echo $token; ?>" />
Amount: <input type="hidden" name="token" value="100 usd" />
<input type="submit" value="submit" />

</form>
</body>
</html>

然后,当涉及到实际插入记录时:

Then when it comes to actually inserting the record:

payment_save.php

<?php
 session_start();
 $token = $_SESSION['payment_token'];
 unset($_SESSION['payment_token']);
 session_write_close();
 if ($token && $_POST['token']==$token) {
   // Insert the record for payment
 } else {
   // log message. You are vulnerable to CSRF attack.
 }
?>

令牌应该很难猜到,对于每个插入请求都是唯一的,只能通过$ _POST接受,并在几分钟后过期 (未在此图中显示过期).

The token should be hard to guess, unique for each insert request, accepted via $_POST only and expire after a few minutes (expiration not shown in this illustrations).

这篇关于提交密码的最佳做法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆