PplWare Mobile

PHP é à quinta-feira – Sistema de Login com sessões

                                    
                                

Este artigo tem mais de um ano


Autor: Pedro Pinto


  1. QT says:

    Excelente tutorial 🙂
    já tive a experiência de usar estes codigos, mas quem precisar duma ajudinha, esta aqui um tutorial espectacular 🙂

  2. FXX says:

    Muito bem explicado, apesar de já conhecer esta forma de login acho que foi muito bem explicado.

    Seria possível darem um exemplo recorrendo à encriptação MD5?

    • malaiCo says:

      Muda esta linha:
      $consulta=”Select * from utilizadores where email='” . $_POST[‘email’] . “‘ and password='” . $_POST[‘password’] . “‘”;
      Para ficar assim:
      $consulta=”Select * from utilizadores where email='” . $_POST[‘email’] . “‘ and password='” . md5(trim($_POST[‘password’])) . “‘”;

      • FXX says:

        Obrigado. Já agora só mais uma pergunta, para poder usar a função md5() na verificação do login, a password tem de ser registada na BD já encriptada pela função md5 também?

      • Pedro says:

        Não deverias fazer o md5(trim($_POST[‘password’])), e sim o md5($_POST[‘password’]). A diferença? Se alguém tivesse um espaço no primeiro caracter ou no último, este iria desaparecer. Nunca se deveria fazer trim de uma password…

    • JGomes says:

      caso seja um projecto “a sério” recomendo a função sha1 (mais seguro que o md5) e adicionar uma string única à password (eg. username ou uma string aleatória guardada juntamente com o registo do utilizador na base de dados) para tornar as rainbow tables (tabelas de correspondências de hashes) inúteis caso o servidor seja comprometido.

      Cumprimentos

  3. Para um MD5, basta que graves a password na bd em MD5, e a quando o login convertes a password inserida em MD5 e comparas com a guardada na BD.

    convertes assim:
    md5(“$password”)

    Cumps.

  4. Nuno says:

    há algumas coisas no tutorial que não devem ser feitas, a password deve ficar codificada e a password comparada fora do query. permite injecção de sql

    • RCS says:

      Para além de ser codificada, deve se-lo em forma de hash, de forma a nunca se conseguir obter a password original. E não usem md5 sff, isso já não é seguro faz tempo. Optem pelo sha ou sha2.

      De qualquer das maneira, foi um bom post. Está bem explicado e é sem dúvida um tema interessante.

    • Pedro Peixoto says:

      Boa noite,
      Tal como eu disse inúmeras vezes no tutorial isto é um tutorial simples. Este tema dava para muita conversa. O objectivo aqui é dar as luzes de como funciona um sistema de login.
      Como disse no início “Obviamente, isto dava tema para uma tese, mas aqui vamos ser directos e objectivos.”, este tutorial é destinado a quem não sabe fazer e por isso tem que ser simples, claro que para quem já entende alguma coisa, parece que não custa nada adicionar a encriptação da password, ou proteger contra sqlinjection mas quanto mais complicamos pior… Até assim este artigo já está mais extenso do que devia…

      Cumprimentos

  5. kwan says:

    Tens uma grande falha de segurança, na parte de select à base de dados, não deves por o post directamente na query sem filtrares os dados.

    Cheers

  6. H-Ramos says:

    Deves usar sempre as funções sprintf() e mysql_real_escape_string() para ficares protegido contra injection:

    // Query
    $query = sprintf(“SELECT * FROM users WHERE user=’%s’ AND password=’%s'”, mysql_real_escape_string($user), mysql_real_escape_string($password));

    // SQL
    $sql = mysql_query($query) OR die(mysql_error());

    http://php.net/manual/en/function.mysql-real-escape-string.php

    Ou então alteras o php.ini logo de vez.

    • Pedro Peixoto says:

      Certo, apenas não quis complicar. Estes comentários são bastante positivos, complementam o artigo, assim quem percebeu tudo e quer complementar pode ver o código melhorado. Faz-me lembrar as páginas de ajuda do PHP, tem o básico e por baixo podemos ver os comentários com melhorias, métodos de uso, etc… Obrigado, vocês acabam por serem co-autores dos artigos. 😀

      • Ricardo Elias says:

        Qual e’ a complexidade de codigo introduzida pelo uso de mysql_real_escape_string, que evita erros de sintaxe e SQL Injections, que um utilizador que pretende criar uma versao basica de login nao consegue compreender?

        Versao 1:
        $consulta=”Select * from utilizadores where email='” . $_POST[‘email’] . “‘ and password='” . $_POST[‘password’] . “‘”;

        Versao 2:
        $consulta=”Select * from utilizadores where email='” . mysql_real_escape_string($_POST[‘email’]) . “‘ and password='” . mysql_real_escape_string($_POST[‘password’]) . “‘”;

        Fiquem Bem!

        • Pedro Peixoto says:

          Não é nenhuma, eu até posso meter o código de um sistema de login todo XPTO, mas aqui o objectivo não é decorar código é aprender, compreender e perceber porque se faz assim. Estejam descansados que hade vir um artigo onde seja explicado o SQL injection e as maneiras de resolver e onde as funções sejam explicadas em pormenor. Quando aprendi, aprendi assim, começando por baixo e posso dizer que aprendi bem, por isso é assim que vou explicar porque na minha óptica é a melhor maneira de aprender. Obrigado pelo contributo.

        • Meu caro, a questão é que você já sabe. Para quem está aprendendo, muitas informações podem sim confundir, afinal quem procura esses assuntos geralmente quer aprender a fazer e não só copiar e colar.

          Se for só para copiar e colar, você pode colocar 300 páginas de código que um garoto de 10 anos vai conseguir implantar o sistema de login. Mas se for para aprender e quem sabe um dia conseguir fazer sozinho tem que ser aos poucos mesmo.

          A pessoa aprende o básico e depois vai incrementando.

          Eu acho assim, muitas pessoas não querem dedicar seu tempo a criar tutoriais, mas sempre encontram uma forma de criticar o trabalho alheio. Acha que não está bom? Faça melhor. E não venha com essa de que está só querendo ajudar, ou acrescentar algo.

  7. IRONLORD says:

    Muito obrigado,

    Andei a semana passado a recolher algum conhecimento àcerca de sessões, e com este tutorial, fiquei mais esclarecido.

  8. Anon says:

    Por falar em passwords, parece que houve problemas no lastpass.com, já alterei todas as que são mais importantes e recomendo, por uma questão de segurança, que também o façam.

    Já agora NUNCA passem a variável $_POST[‘variable’] directamente para a query, se implementarem um sistema destes recomendo uma vista de olhos no PDO

    http://php.net/manual/en/book.pdo.php

    Os prepared statements permitem evitar a possibilidade de sql injection ( e o PDO permite uma grande portabilidade de código entre sistemas de base de dados)

    Cumprimentos

  9. rodasp says:

    Já que se tocou neste assunto alguém pode-me dizer como faço para limitar o número de tentativas de login?

    Ex: Falhou a pass 3x só pode fazer login daqui a 15min…

    Eu tenho uma ideia, mas não sei se é a mais correcta… criar uma variável de sessão com o numero de segundos pretendidos. E depois criar um ciclo até que os segundos cheguem a zero.

    Obrigado pelas rubricas.. estamos sempre a apreender xD

    • Pedro Peixoto says:

      Boa noite, se queres que as tentativas sejam permanentes, podes adicionar um campo na base de dados com o número de tentativas falhadas, e quando falha incrementas o seu valor. Quando faz login verificas se o numero de tentativas já passou as 3 e não deixas fazer login.

      • rodasp says:

        Não quero permanente.. basta uns 15min.

        Mas deste-me uma ideia melhor… gravo um número de tentativas e a hora da ultima tentativa de login e depois compara a hora a que está a tentar fazer o novo login com a hora que está na base dados (a da última tentativa). fiz-me entender?

        (Viperz0r.. não existe nenhum link…)

    • Viperz0r says:

      Dá um vista de olhos, pode ser que seja isto que queiras.

    • Mr. PI says:

      Eu posso ajudar nisso! Já fiz isso em vários sistemas de login. Inclusive, verificar quantas vezes errou no mesmo IP, a que horas, etc…

      Cumpts,
      Mr. PI

  10. Mandrake says:

    Faço igual vcs ensinaram a algum tempo.
    Simples e funcional.

    Show de bola.
    Bem que podia rolar umas aulas de CakePHP. =D

  11. visitante says:

    Parabéns 🙂

  12. Mr. PI says:

    Boas pessoal!

    Por acaso já alguém usou o SHA512 num sistema de login em PHP? Eu usei num sistema que criei e não tive qualquer tipo de problema.

    Qual a vossa opinião do SHA512 para o SHA1?

    Sinceramente acho que nos dias de hoje o uso da encriptação MD5 num sistema de login fica muito fraco.

    Penso que o melhor a fazer para melhorar a segurança, é:

    – Criar um SALT;
    – SHA512;
    – Encriptar a mesma password 10 ou mesmo 15 vezes (se for um sistema com poucos users, caso contrário pode puxar muito pela base de dados);
    – Guardar o IP do cliente;
    – Criar um sistema de logs;
    – Enviar um email ao admin cada vez que houver uma tentativa errada de login…

    Existem muitas coisas para melhorar a segurança.

    Pessoal do PPLWARE, se quiserem posso exemplificar com código tudo o que disse. 🙂

    Cumpts,
    Mr. PI

    • JGomes says:

      Sha1 já é suficientemente seguro visto possuir possibilidades extremamente baixa de colisões, mas não se perde nada em recorrer ao sha-512 visto este recorrer a “palavras” maiores tornando ataques de dicionário ainda menos eficientes. Obviamente que o sha-512 é computacionalmente mais “pesado” que o sha-1, mas não é um grande problema porque as passwords não são suposto serem verificadas em cada carregamento de página (sessões de autenticação / tokens).

      O salt pode-se recorrer ao nome do utilizador como prefixo da password antes de recorrer à síntese segura, mas para ser mais seguro recomendo uma cadeia de caracteres aleatória guardada juntamente com o registo do utilizador (tem que ser única para cada utilizador). O salt faz as tabelas de sínteses (rainbow tables) inúteis caso o servidor seja comprometido, porque o atacante terá que criar tabelas para cada utilizador, o que não é viável de realizar em tempo útil.

      Cifrar varias vezes acaba por ser puro desperdício de recursos computacionais, porque na prática não garante nenhuma segurança.

      Sistema de logs é altamente recomendado para detectar intrusões e modificações não autorizadas.

    • RCS says:

      É preciso ter cuidado com o facto de cifrar várias vezes uma chave, fazer uma comparação com a BD, e de seguida ainda enviar um e-mail ao admin, ser computacionalmente muito mais pesado do que apenas efectuar o login. Ou seja o servidor vai ter muito mais trabalho do que o cliente. É meio caminho andado para entupir o servidor.

      • Mr. PI says:

        Esta opção que referi foi apenas a pensar na segurança. 🙂

        Estas normas que referi, apenas são para sites que tenham poucos users, mas que a informação seja vital, por exemplo um backoffice de uma empresa, em que possam consultar dados criticos da mesma.

        Ainda existem muitas mais normas que poderão ser incluidas no script de login, nomeadamente:

        – Bloquear o user após X tentativas erradas e enviar email ao administrador com o IP, horas dos logins e passwords utilizadas (para vermos se foi utilizado tentativa por dicionário);
        – Verificar se o login vem pelo método $_SERVER[‘REQUEST_METHOD’] == ‘POST’), caso contrário bloquear;
        – Colocarem um sprintf() na query de à base de dados;
        – Na query nunca esquecer de incluir “LIMIT 1”;

        Como disse, existem N coisas que se podem fazer para melhorar bastante a segurança.

        Nunca esquecer de efectuar o log de todos os passos que são efectuados pelo user!

        Cumpts,
        Mr. PI

  13. Milhafre says:

    Muito Obrigado pelo tutorial, veio mesmo a calhar.

    Gostaria de perguntar se não é possível colocar a mensagem de erro do login através de uma box ao invés de aparecer na mesma pagina?

    Cumprimentos,
    Milhafre

    • Rui Pedro Peixoto says:

      Bom dia, sim é facil. Tens que colocar as tags script e depois chamar a função alert com a mensagem. Vou escrever aqui o código mas não sei se vai ser permitido:
      Alteras o código no index.php:
      echo ‘Erro no login. Tente novamente.’;
      para:
      echo ‘alert(“Erro no login. Tente novamente.”)’;
      cumprimentos

  14. Pedro Peixoto says:

    Bom dia, sim é facil. Tens que colocar as tags script e depois chamar a função alert com a mensagem. Vou escrever aqui o código mas não sei se vai ser permitido:

    Alteras o código no index.php:

    echo ‘Erro no login. Tente novamente.’;

    para:

    echo ‘alert(“Erro no login. Tente novamente.”)’;

    cumprimentos

  15. emanuel says:

    Boa tarde, tenho criada uma BD com serca de 400 users, quando meto um utilizador errado ele dá erro (que está certo)…mas quando meto um user e senha correcta manda-me para a pagina admin.php, mas dá-me a mensagem “Esta é uma àrea reservada, só utilizadores podem ter acesso”, dá a impresão que perde a conexão…será que me pode ajudar?

  16. Joca says:

    Não consegui criar a BD, será que pode divulgar o código SQL ?

    Abraços

  17. Rodrigues says:

    O Português só se contenta a criticar e sentir-se o maior… É por isso que em Portugal(Bom país para desenvolvimento de tecnologias) se comem uns aos outros em vez de se ajudarem uns aos outros.

    Pedro, parabéns. Lembro-me que na minha altura os “form’s” eram simplesmente
    $user_bd=mysql_query(….);
    if ($_POST[‘user’]!=$user_db){print ‘Wrong Username!’;
    }else{
    if (…..

    Cumps

  18. Jorge says:

    Muito bom ! Coloquem tudo em ficheiros e partilhem em http://www.mais-codigo.com ! 🙂

  19. Pedro says:

    Alguém poderia dar um exemplo com níveis??!!

  20. login says:

    Quero criar o esquema de login e senha, mas fiz o passo-a-passo do seu vídeo e não consegui, tem como vc me passar seu e-mail ou msn para tentar tirar algumas dúvidas?
    Basta baixar os arquivos no meu ftp?

  21. Adok says:

    Bom e muito esclarecedor, parabens pelo tópico,
    e isso acabou dando pano pra manga e abrir um novo tópico a respeito de segurança em logins imputs de entrada, text area.

  22. Ricardo says:

    Boas,
    Alguem pode dar o ficheiro SQl?

  23. Joana Costa says:

    Boa tarde a todos! Peço desculpa pela minha ignorância no assunto mas efectivamente não sei muito sobre PHP ainda (infelizmente!). Estou a fazer um site em WordPress e, em algumas páginas existe conteúdo que pode ser visto por diferentes utilizadores. Por exemplo: numa página com uma introdução + lista de links…a introdução pode ser vista por todos os utilizadores mas a lista de links apenas por 2 dos 3 tipos de utilizadores. Não sei como fazer isto! Alguém pode dar uma ajuda pf? Obrigada!

  24. Bruno says:

    Tenho uma dúvida: como faço para criar um sistema de login que quando o usuário registrar (criar um login de acesso), cadastrar como TRIAL com 15 dias?

    O usuário terá 15 dias para ter acesso aos conteúdos restritos e, quando passar esse tempo, o acesso bloqueia e aparece uma mensagem de “Compre para continuar acessando”

  25. ARTHUR says:

    Pedro, em qual email posso te enviar um código de login e senha para que vc possa estar me ajudando?

  26. Xavier says:

    Boas
    Tenho uma duvida como e que eu autentico o utilizador???
    De resto esta tudo óptimo.
    Obrigado.

  27. alexandre says:

    Olá, eu to montando um sistema de login , quando inicio a sessão ele exibir a msg de bem vindo ao usuario gostaria de saber como faço para a pagina php buscar dados de outras tabelas pele id que foi atribuída ao usuarios, exemplo, tenho uma tabela de endereço e de usuario na tabela, quando ele se registrar no site o user vai para uma tablela junto com a senha e o endeço cpf reg para outra. gostaria de buscar essas informações e exibir na tela !

  28. João Lopes says:

    Alguém me sabe dizer porque o Xampp dá este erro, ” Call to undefined function mysql_connect()”?

    Obrigado

  29. João Lopes says:

    mysqli_select_db() expects parameter 1 to be mysqli, string

    o meu codigo é este:

  30. Ricardo Rosa says:

    No php.ini vê se estas a fazer o load da dll

    extension=php_mysql.dll

  31. Zé Manel says:

    MD5 e SHAx são algoritmos de hashing e não de cifra!

  32. susana says:

    Boa noite,

    Alguem me pode ajudar de como posso fazer para que alguns menus estejam visiveis para o utilizador e todos estejam visiveis para o administrador?

Deixe um comentário

O seu endereço de email não será publicado.

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

Aviso: Todo e qualquer texto publicado na internet através deste sistema não reflete, necessariamente, a opinião deste site ou do(s) seu(s) autor(es). Os comentários publicados através deste sistema são de exclusiva e integral responsabilidade e autoria dos leitores que dele fizerem uso. A administração deste site reserva-se, desde já, no direito de excluir comentários e textos que julgar ofensivos, difamatórios, caluniosos, preconceituosos ou de alguma forma prejudiciais a terceiros. Textos de caráter promocional ou inseridos no sistema sem a devida identificação do seu autor (nome completo e endereço válido de email) também poderão ser excluídos.