Pergunta

Estou criando um site PHP que envolve os usuários se inscrever, e eu estou querendo saber sobre as melhores práticas para códigos de "confirmação de e-mail".

Os novos usuários devem confirmar seus endereços de e-mail - Eu faço isso através da geração de um código e enviá-lo para o usuário em um e-mail, que ele pode usar para ativar sua conta. Em vez de armazenar essa chave em um banco de dados, eu estou usando um pouco de solução alternativa acessível: o código é o resultado de:

md5("xxxxxxxxx".$username."xxxxxxxxxxx".$timestamp."xxxxxxxxx");

Onde $ timestamp se refere ao tempo de criação de usuário. Em toda a I foi muito satisfeito com isso, mas depois eu comecei a pensar, isso é suficiente seguro? E sobre a possibilidade de colisões? E eu também preciso para gerar códigos de redefinição de senha, etc. Se eu utilizar uma metodologia semelhante, uma colisão pode resultar em um usuário, inadvertidamente, redefinir a senha de outro usuário. E isso não é bom.

Então, como você faz essas coisas? Meus pensamentos era uma tabela com o seguinte formato:

codePK (int, a-I), userID (int), type (int), code (varchar 32), date (timestamp)

Onde 'tipo' seria 1, 2 ou 3 que significa "ativação", "Alterar e-mail" ou "redefinição de senha". Será esta uma boa maneira de fazê-lo? Você tem uma maneira melhor?

Usando um método semelhante ao anterior, poderia qualquer coisa que eu automaticamente exclusão ao longo de dois dias de idade sem o uso de cron-jobs? Meu anfitrião (nearlyfreespeech.net) não apoiá-los. Se possível eu gostaria de evitar ter um posto de trabalho cron em um host externo que wget é um script que exclui as coisas, como isso é apenas confuso = P.

Obrigado!
Mala

Update:
Para esclarecer: eu percebi o único caminho a percorrer de forma segura e com segurança sobre esta tarefa é usando um banco de dados, que é o que a função original estava tentando evitar. A minha pergunta é sobre a forma como a tabela (ou tabelas?) Deve ser estruturado. Alguém sugeriu que eu acabar com codePK e apenas fazer o código de um PK. Assim, em breve, a minha pergunta é: é isso o que você faz

Foi útil?

Solução

Quando eu precisar destes tipos de truques é normalmente de uma de duas razões, ambos mencionados por você:

  1. Como uma chave usada para e-mails de verificação enviado para o usuário
  2. Como uma chave usada para links de redefinição de senha

É claro que haveria muitas outras ocasiões em que você consideraria usar uma tal construção.

Em primeiro lugar, você deve sempre usar algum tipo de sal que está escondido e que só você sabe. Note-se que este sal deve ser diferente para cada usuário. O sal pode, por exemplo, ser calculado como sha256(something random). Este sal deve então ser armazenado no banco de dados juntamente com o nome de usuário e senha (hash com o sal).

O que eu faria ao enviar o link de redefinição de senha é criar outro sal (não dão o acesso do usuário a qualquer coisa hash com o seu sal. Ele conhece sua senha, portanto, usando bruteforce ele poderia descobrir o seu sal). O outro sal, que é essencialmente apenas uma hash de um cadeia aleatória (você pode querer ir para md5 aqui, como você mencionou que o comprimento é um problema), você deve, em seguida, salvar em seu banco de dados.

Muitas vezes você pode simplesmente fugir com a adição de uma coluna adicional para sua tabela de usuários. Isso, no entanto, também tem alguns problemas, principalmente, que uma vez que a senha foi redefinida ou o usuário tenha sido ativada, você irá remover a chave do banco de dados, o que resulta na maioria das linhas que têm valores nulos, que por sua vez traz algum outro problema .

O que isto essencialmente se resume a:

  • senhas hash de seus usuários usando um sal único-para-o-usuário ( e , talvez, um, sal segredo global).
  • Gere uma chave de hash um número de fontes aleatórios ou pseudo-aleatórios como timestamps, mt_rand() ou mesmo random.org se você realmente quiser coisas aleatórias.
  • Nunca use seu sal global ou o sal que é exclusivo para o usuário para hash qualquer coisa que o usuário obtém acesso, incluindo chaves de redefinição de senha, chaves de ativação, etc.

Por favor, não que eu sou de nenhuma maneira um especialista em segurança, e eu provavelmente ter esquecido uma série de coisas, e eu pode ter mencionado algumas coisas práticas muito ruins. Apenas meus 5 centavos; -)

Outras dicas

Por que usar qualquer um dos dados do usuário como base para a chave de autorização?

Eu presumo que você está armazenando os dados de-ativados em um banco de dados então por que não basta adicionar um registro adicional que é simplesmente uma chave aleatória (talvez um md5'ed uniqid com alguma manipulação adicional) e, em seguida, verificar contra isso?

Foi seguro até certo suficiente até o ponto onde você publicou o seu método na internet! Isto é porque você estava contando com segurança por obscuridade, o que não é uma boa idéia.

Você deve usar algum tipo de função com chave de hash ou MAC idealmente, que incorpora uma chave secreta conhecida apenas por você.

Por que não fazer índice exclusivo campo de código? Então, nunca haverá collsisions?

Além disso, se você não precisa criar hash entrada do usuário e combiná-lo com hash de banco de dados (e-mail de confirmação, de redefinição de senha etc) - você pode adicionar seqüência aleatória para o corpo de hash, como md5('xxx'.$username.'xxx'.time().'xxx'.rand())

Por que não pedir que o usuário insira seu nome de usuário e seu código, eliminando assim qualquer problema com a colisão? Você faz qualquer coisa para não perder em termos de segurança como você ainda está pedindo a chave que deseja obter a partir do e-mail, mas você parasse de eles serem capazes de redefinir senhas de outros usuários.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top