Login system with PHP [closed]

2

Hello, I need to do an administrative area, and obviously I need a login system and password. I know there are already questions here, but I fear they are outdated. I want a way inside the simple and safe possible. I also do not want anyone to do anything for me, because I'm learning and obviously I want to master it, I just want them to give me tips on how to do it, reference links and so on. Thank you in advance.

What I have so far:

<form action="submit" method="POST">
    <h1>LOGIN:</h1>
    <input type="text" name="login">
    <h1>SENHA:</h1>
    <input type="password" name="password">
    <button type="submit">ENTRAR</button>
</form>
    
asked by anonymous 07.12.2015 / 18:46

5 answers

6

Forget SHA1 and MD5

Before you start, it's good to make it clear. Do not use any of these encryption methods. You will understand why in the course of this answer.

Important information

I recommend that you read this response, then read this Thiago Belem article, then this article from the PHP documentation itself.

The links above will show why you should not use sha1 or MD5.

In the case of the second link I passed, do not just read, but execute what was taught and run again until you know what is being done. After that, I also recommend the process using the instructions from the third link, password_hash

I will not reinvent the wheel here, because the first link already has everything you need to know and the rest are the encryption exercises.

I'll give you an example solution for your case, simple and commented for you to understand. In the example I will use password_hash , which is the safest method currently.

Example usage

No HTML

<form action="" method="post">
    <label for="login">Login</label>
    <input type="text" name="login" id="login">
    <label for="senha">Senha</label>
    <input type="password" name="password" id="password">
    <button type="submit">Fazer login</button>
    <input type="hidden" name="hidden" <?php echo "value='" . $_SESSION['formKey'] . "'" ?>>
</form>

No action does not need to put anything, since we will use the same form page to validate the data.

If you've read the first link I've passed, you should know that the input field of type hidden is used to make it difficult for% (Cross-site Request Forgery), where the form will only be validated if the value of ataques do tipo CSRF is equal to the value of hidden . Remember that this $_SESSION['formKey'] should be changed every time the page is updated, after passing the $_SESSION method validation, of course. In PHP code you will understand.

I recommend that you read this article on CSRF attacks.

The labels issue is just an aspect of $_POST , where you allow the user to click the label, and the focus is directed to the input.

In PHP

<?php

    //Possibilita que trabalhemos com sessões, vai ser útil para validar o campo
    //hidden, e também para manter o usuário logado no sistema.
    //mas isso é outro ponto e não vou abordá-lo aqui.
    session_start();

    //Dados do banco
    $hostname = 'localhost';
    $username = 'root';
    $password = '123456';
    $database = 'meusite';

    //Se conecta ao banco de dados
    $mysql = mysqli_connect($hostname, $username, $password, $database);
    mysqli_set_charset($mysql, 'utf8');

    //Se o usuário clicar em submit, ele faz uma requisição POST e aciona
    //essa condição
    if ($_SERVER['REQUEST_METHOD'] == 'POST') {

        //Verifica se o valor do campo hidden bate com o valor da session.
        if (isset($_POST['hidden']) && $_POST['hidden'] == $_SESSION['formKey']) {

            //Verifica se existe um POST chamado login e senha respectivamente e,
            //se existir, remove os espaços no começo e final da string usando a função
            //trim() e atribui o valor deles as respectivas variáveis.
            //Se não existir, define o valor da variável como null.

            //Se não entendeu como funciona, pesquise sobre OPERADOR TERNÁRIO e função TRIM
            $login      = (isset($_POST['login'])) ? trim($_POST['login']) : null;
            $password   = (isset($_POST['password'])) ? trim($_POST['password']) : null;

            if (empty($login)) {
                //Se a variável $login estiver vazia, faça:
                echo 'Por favor, preencha o campo de login';
                exit;
            }
            if (empty($password)) {
                //Se a variável $password estiver vazia, faça:
                echo 'Por favor, preencha o campo de senha';
                exit;
            }

            //Antes de comparar qualquer dado com o banco, fazemos escape para dificultar
            //SQL injections.
            $login      = mysqli_real_escape_string($mysql, $login);
            $password   = mysqli_real_escape_string($mysql, $password);

            //Seleciona os campos login e password na tabela usuarios, cujo login seja
            //igual ao login informado no formulário.
            //Lembre-se de marcar a coluna login no banco de dados como UNIQUE ID
            //para que não seja possível existir mais de um login igual.
            $result = mysqli_query($mysql,
            "SELECT 'login', 'password' FROM 'usuarios' WHERE 'login' = '" . $login . "'");

            if(!mysqli_num_rows($result)) {
                echo "Usuário não encontrado";
                exit;
            } else {
                //Coloca os dados retornados pelo banco em um array chamado $data
                while ($r = mysqli_fetch_assoc($result)) {
                    $data[] = $r;
                }
            }

            //Chegando neste ponto, entede-se que o login informado existe, agora temos que
            //validar a senha.

            //Vamos supor que você usou password_hash para criptografar a senha no
            //momento do cadastro do usuário.

            if (password_verify($password, $data[0]['password'])) {
                echo "Logado com sucesso!";
            } else {
                echo "Senha incorreta!";
                exit;
            }

            //Fazendo isso, estamos dizendo pro PHP verificar se a senha informada
            //corresponde ao hash (senha criptografada) que estava no banco.
        }
    }

    //Toda vez que ele atualizar a página, o value do campo hidden será alterado
    //Abaixo fizemos o sha1 de um número randomico usando a função rand().
    $_SESSION['formKey'] = sha1(rand());

    //Eu usei sha1, porque? Simples. O valor do campo hidden não tem importancia
    //pra gente. Ele não precisa ser seguro, até porque ele será visível caso
    //o usuário clique em visualiar o código fonte, ele só precisa mudar e ser
    //impossível de se acertar num "chute".
?>

The recipe for the cake is there, just use it.

    
07.12.2015 / 20:09
6

Something I see a lot in the tutorials I encounter on the internet is that they separate the presentation configuration, but do not use as we see on most of the websites that people create today, they simply separate those files through directories, so you can program without using

07.12.2015 / 19:55
2

Take a look at this blog: An object-oriented example using PHP. For password use SHA1: Passwords

    
07.12.2015 / 19:10
2

I recommend giving a study also in MD5 (or SHA1 as our friend @Bia mentioned). Also look at Login Validation by Sessions . And, if you want, take a look at SQL Inject to learn more about the security flaws that STILL exist on many sites. Good studies!

PS: A similar topic already exists: Best way to make a login system and password with PHP

    
07.12.2015 / 19:21
1

Briefly: As you are now starting, the first step I can suggest to study, before making a login system and password, is to follow the normalization of PSRs , after all, we do not want bad codes made there anymore.

The second step is, where possible, consult PHP Official Documentation .

This site has plenty of information for anyone who needs to learn how to develop with PHP.

To make a login system, you will basically need:

  • Connection to database
  • Session setup
  • Create user, password, and hash
  • >

    For pages that you have access restriction, you should create access levels for users, one way to do this is giving weight to the user, in the example below, I will give 3 pesos, 0 - blocked, 1 - editor , 2 - administrator.

    User table:

    CREATE TABLE 'User' (
      'id_user' int(11) NOT NULL AUTO_INCREMENT,
      'username' varchar(45) NOT NULL,
      'password' varchar(255) NOT NULL,
      'createdAt' TIMESTAMP NOT NULL DEFAULT current_timestamp,
      'salt' varchar(255) NOT NULL,
      PRIMARY KEY ('id_user'),
      KEY 'username' ('username')
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Dados do Usuário';
    

    User Profile Table:

      CREATE TABLE 'Roles' (
      'id_role' int(11) NOT NULL AUTO_INCREMENT,
      'fk_user' int(11) NOT NULL,
      'level' int(9) NOT NULL DEFAULT '0',
      'name' varchar(45) NOT NULL,
      PRIMARY KEY ('id_role'),
      KEY 'fk_Roles_1_idx' ('fk_user'),
      CONSTRAINT 'fk_Roles_1' FOREIGN KEY ('fk_user') REFERENCES 'User' ('id_user') ON DELETE NO ACTION ON UPDATE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Níveis de acesso do Usuário';
    

    Now, to check the access levels, you would make an inquiry of this type, picking up all users that are not blocked ( 0 ):

    function createPassword($pass)
    {
     //salve isso no User.password 
      return password_hash($pass, PASSWORD_DEFAULT);
    }
    
    function checkLogin($user, $pass, $dbh)
    {
    
    $sth = $dbh->prepare("SELECT Users.password as pass_hash AND Users.username :=user");
    $sth->bindParam(':user', $user, PDO::PARAM_STR);
    $sth->execute();
    $resultHash = $sth->fetch(PDO::FETCH_OBJ);
    if (validPassword($pass, $resultHash->pass_hash)) {
    
       $sth = $dbh->prepare("SELECT  Users.id_user as 'ID',
                                     Users.username,
                                     Roles.name,
                                     Roles.level
                             FROM    Users
                             INNER JOIN Roles ON
                                     (User.id_user=Roles.fk_user
                                      AND  Roles.level != 0)
                             WHERE   Users.username :=user
                          ");
       $sth->bindParam(':user', $user, PDO::PARAM_STR);
       $sth->execute();
       $result = $sth->fetch(PDO::FETCH_OBJ);
       createSession($result);
     }
    }
    
    function validPassword($pass, $hash)
    {
      return password_verify($pass, $hash);
    }
    

    So basically, you will check the login. And as soon as you confirm, you create the session:

    function createSession($dados)
    {
        session_start();
        $_SESSION['level_user'] = $dados['level'];
        $_SESSION['ip_user'] = $_SERVER['REMOTE_ADDR'];
        $_SESSION['tipo_user'] = $dados['name'];
        $_SESSION['username'] = $dados['username'];
    }
    

    And then check if the user is logged in and his level:

     function checkSession($nivel)
     {
        session_start();
        if ($_SESSION['level_user'] == $nivel && $_SESSION['ip_user'] == $_SERVER['REMOTE_DDR'] &&  isset($_SESSION['username'])) {
               //permitido
        } else {
              //não permitido
        }           
     }
    
        
    07.12.2015 / 22:50