Pergunta

Quero evitar vários logins em um aplicativo PHP.

Primeiro, crio o status de login (ativo, notativo) em uma tabela de usuários.

Quando o usuário A logs no status do usuário será definido como 'ativo' e se o usuário fizer o login, o status será definido como 'Notactive'. Quando outro cliente tenta fazer login usando a mesma conta do usuário, verifico a tabela de usuários. Se o usuário ainda estiver ativo, o login de erros será enviado ao usuário.

O problema ocorreu, se o usuário fechar o navegador, o status na tabela de usuários poderá ser atualizado porque o usuário não clicaria em logout.

Você tem alguma sugestão sobre isso?

Foi útil?

Solução

(Observe que, embora a técnica aqui ainda seja válida; as amostras de PHP não devem ser copiadas literalmente, pois existem meios mais seguros de incorporar valores fornecidos pelo usuário em uma consulta SQL)


Em vez de armazenar se o usuário está ativo inativo, é melhor armazenar algum atributo que pode ser verificado contra o usuário por ação; Como toda vez que o usuário tenta fazer algo que requer autenticação, ele verá para ver se esse atributo corresponde antes de prosseguir.

Eu recomendo que você faça o seguinte;

Primeiro, crie um hash para identificar exclusivamente o usuário sempre que ele faz login. Eu imagino que um sha1 do time() seria suficiente para evitar colisões. O que você escolher, verifique se é variado o suficiente para que outro usuário faça login tenha uma chance incrivelmente baixa de receber o mesmo hash (por exemplo, não hash o endereço IP ou o agente do usuário do navegador, pois não são variados o suficiente).

Segundo, armazene este hash em seu banco de dados e no usuário sessão No momento do login. Fazer isso efetivamente 'logout' o usuário anterior, pois o hash deve ser diferente cada vez que alguém efetua login.

Como estamos usando sessões, um cookie deve ser colocado automaticamente no navegador do usuário, que conterá um ID exclusivo que identifica o usuário aos dados da sessão. O conteúdo do cookie não é realmente preocupante.

Em seguida, crie uma função chamada authenticateUser() ou similar, que será chamado no início de cada script para garantir que o usuário seja autenticado. Esse script deve consultar o banco de dados, verificando se um usuário com o ID do seu usuário tem um hash que corresponde ao hash do seu usuário.

Por exemplo:

function authenticateUser($id, $hash, $databaseLink) {
    # SQL
    $sql = 'SELECT EXISTS(
               SELECT 1
               FROM `tbl_users`
               WHERE `id` = \''.mysql_real_escape_string($id).'\'
               AND `hash` = \''.mysql_real_escape_string($hash).'\'
               LIMIT 1
           );';

    # Run Query
    if ($query = mysql_query($sql, $databaseLink)) {
        # Get the first row of the results
        # Assuming 'id' is your primary key, there
        # should only ever be one row anyway.       
        $result = mysql_fetch_row($query);

        # Casting to boolean isn't strictly necessary here
        # its included to indicate the mysql result should
        # only ever been 1 or 0.
        return (bool)($result[0]);
    } else {
        # Query error :(
        return false;
    }
}

Então, simplesmente passamos authenticateUser() o usuário ID, hash (de acordo com os dados da sessão) e um database link (Para uma conexão de banco de dados, você terá que ter aberto anteriormente).

Se authenticateUser() retorna true, o usuário é autenticado. Se false, o usuário não está ou o banco de dados não está disponível ou há um erro SQL.

Observe, no entanto, que isso aumentará o carregamento do seu servidor como uma solicitação de banco de dados é enviada uma vez por solicitação de página. Provavelmente não é tão sábio fazer isso em projetos gigantes, onde milhares de pessoas estão fazendo login a qualquer momento. Tenho certeza de que alguém pode sugerir melhorias.

Além disso, esperar que o cookie expire não é a melhor maneira de forçar as pessoas que estavam inativas a sair, pois você nunca deve confiar em cookies. Em vez disso, você pode adicionar uma coluna chamada last_active que você pode atualizar sempre que o usuário é autenticado. Isso também aumentará a carga do servidor, mas permitirá que você substitua manualmente log-ins obsoletos, removendo o hash Para usuários que estavam, digamos, inativos por 3 horas.

Outras dicas

Aqui está uma solução que não requer constante Acesso ao banco de dados trabalhar...

(que evitará o requisito de verificar o session_id () em relação ao valor do banco de dados toda vez que solicitar/atualizar uma página, aliviando o estresse do banco de dados/servidor) ...

1. No login, pegue a session_id pré-existente armazenada no banco de dados para este usuário e faça isso:

session_id("the pre-existing session id in the database goes here");
session_start();
session_destroy();

2. Em seguida, inicie uma nova sessão e salve esta nova session_id no banco de dados, substituindo a anterior. Isso fará logou com a sessão anterior sobre esse usuário se houver um ativo (efetivamente registrando o outro cara usando esta conta).

Experimente e deixe -me saber se isso faz o truque !!

Você pode alterar seu modelo para que apenas o usuário mais recente possa ser conectado.

Se você gravar o ID da sessão mais recente visto para cada usuário, quando eles efetuam login uma segunda vez, poderá destruir qualquer sessão existente, registrando -os efetivamente.

Para um usuário normal, as coisas parecem "apenas funcionar". Se você deseja impedir que os usuários "anormais" distribuam suas credenciais de login, isso deve servir como um desincentivo.

O que você deve fazer é verificar se eles estão ativos nos últimos minutos ao tentar fazer login. Isso pode ser feito com um carimbo LastOnline e deve ser definido em todas as solicitações de página na tabela de usuários.

Se não for feito com JavaScript, você poderá verificar, ao fazer login, se o usuário estivesse ativo nos últimos 15 minutos. Caso contrário, você pode fazer login como o novo usuário.

Você também pode fazer isso com JavaScript. Faça uma chamada de Ajax que dispare a cada minuto ou mais.

<script>
setInterval(function() {
  // do the ajax call
}, 60000);
</script>

Deixe esta chamada vá para um script que editará o carimbo LastOnline no banco de dados do usuário. Ao tentar fazer o login, você verifica o DB do usuário se o carimbo LastOnline excedeu o minuto e você terá sua verificação, se puder fazer o login. Isso ajudará quando você estiver na página, mas você não estiver ativo nos últimos 15 minutos e não deseja que outra pessoa faça login.

Você precisa criar um ID e armazenar exclusivo que em um banco de dados. O que eu fiz foi criar também. Armazeto um em uma variável de sessão e uso isso para impedir o seqüestro de sessão e outro em um banco de dados para evitar vários logins. O código a seguir criará um ID exclusivo:

$unique_id = sha1('xzr4'.gethostbyaddr($_SERVER['REMOTE_ADDR']).$random_string.$_SERVER['HTTP_USER_AGENT'].'f8k2');

Se o ID exclusivo não corresponder, basta registrar o usuário.

O uso do JavaScript do lado do cliente para rastrear o usuário conectado não é confiável.

Você pode obter o mesmo resultado simplesmente criando um campo LastLogindate no banco de dados e atualizando -o com o último registro de data e hora de login do usuário.

Em todas as tentativas de login, se agora ()-$ lastLogindate> predefined_timeout, você deverá aceitar o novo login, caso contrário, recusá-lo.

Esta solução é semelhante à do Programammer, mas não exige que você mexa nas sessões de troca. Não exige que você acesse o banco de dados em todas as páginas e não bloqueie o usuário depois que eles não fizeram o login.

Adicione um campo para sessionID à sua tabela de usuários no banco de dados.

Defina o manipulador de sessão padrão antes de ligar para session_start () (necessário para a próxima linha de código funcionar):

session_set_save_handler(new \SessionHandler());

Em todos os login bem -sucedidos, recupere o $ sessionID armazenado no banco de dados. Destrua a antiga sessão com:

(new \SessionHandler())->destroy($sessionID);

Obtenha o novo ID da sessão com:

$sessionID = session_id();

Armazene o novo ID da sessão no banco de dados.

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