What I'm thinking of doing is "hanging out" with a session_destroy()
when the same user logs in somewhere else.
Is there a way to do this?
What I'm thinking of doing is "hanging out" with a session_destroy()
when the same user logs in somewhere else.
Is there a way to do this?
Your question was confusing, but I'm going to try to break down some of the possibilities that I came to realize with your question.
Situation One / User Logged
The user is logged in and we currently have a session for this user.
The user tried to login again in another browser, the system will create another session for this same user.
The system in this scenario is allowing the user to log on multiple times without restriction.
Situation Two / Validating Session
The user is logged in and we currently have a session for this user.
Situation three / Destroy Session
The user is logged in and we currently have a session for this user.
I want to close the session in PHP we can use session_destroy (), this function will remove all session from this user, all created variables will be destroyed or it will destroy all data associated with the current session, it does not delete any of the global variables associated with the current session, nor does it delete the session cookie, to use session variables again, session_start () must be called.
Important Note that it is not necessary to call session_destroy (), instead of destroying session data, clear the $ _SESSION array and that's it.
Another important point is that if $ _SESSION (or $ HTTP_SESSION_VARS for PHP 4.0.6 or lower) is used, use unset () to unregister the session variable, ie unset ($ _SESSION ['varname']);Caution
Do not completely eliminate $ _SESSION with unset ($ _ SESSION) since this will disable the logging of session variables through the super global $ _SESSION.
You can also use session_unset (void) which frees all registered session variables.
Session in File or Redis
There is the possibility of using session in file that is already the default configuration currently, or in database like Redis, the behavior is transparent in both cases.
Managing logged-in user sessions
In applications we need to manage the environments and not allow users logged in multiple times, times of system use and prohibit access, need to check if the user is online or overturn the system.
In this scenario mentioned above, you can implement reading the session file either in a file or in a database.
I'll show you how to do this by reading a file for example:
We have the function session_decode it decodes the serialized session data provided in $ data and fills the super global $ _SESSION with the result.
The code looks like this:
$pathFile = "/tmp/sess_vvk5ff5u1jjabatog0353pce4lc3mpc9";
$conteudo = file_get_contents($pathFile);
session_decode($conteudo);
print_r($_SESSION);
The disadvantage of this feature is that it puts everything in $ _SESSION, and will not have a result you'd like.
The other and safest way is to decode the file it has a default and using unserialize you will be able to create a vector with all the variables that is in the session.
The method or function to do the session file decryption would look like this:
while ($offset < strlen($conteudo_session)) {
if (!strstr(substr($conteudo_session, $offset), "|")) {
throw new Exception("invalido o seu conteudo " . substr($conteudo_session, $offset));
}
$pos = strpos($conteudo_session, "|", $offset);
$num = $pos - $offset;
$varname = substr($conteudo_session, $offset, $num);
$offset += $num + 1;
$data = unserialize(substr($conteudo_session, $offset));
$return_data[$varname] = $data;
$offset += strlen(serialize($data));
}
return $return_data;
In this way you can find out if your user is online, you can take down a user even if you are connected to another user, you can make a script to check if the user can log in at that moment and several other possibilities.
Well I hope to have helped, although it is not clear the question left some comments on session_destroy that may be useful.
You can make sessions predictable, for you. This has a risk involved, but so you could destroy the previous session, knowing the current state.
In theory the idea my idea is simple, in the database you would have:
Id | Usuario | ... | Semente | Estado
1 | Alice | ... | (Aleatório) | 1
2 | Bob | ... | (Aleatório) | 5
It would also have a fixed key, preferably out of code, as in an environment variable, but not in the same database location / server. But to facilitate understanding, something like:
$ChavePrivada = '...'; // Chave de 512 bits aleatória.
So you would have to do:
HMAC(HMAC( {ESTADO} , {SEMENTE} ), {CHAVE PRIVADA DA APLICAÇÃO})
That way, for example, in Alice's case:
HMAC(HMAC('0', 'ABCDE... Aleatório'), 'ASDFG... Aleatório'))
When Alice logs in again, you will:
HMAC(HMAC('1', 'ABCDE... Aleatório'), 'ASDFG... Aleatório'))
//...
HMAC(HMAC('2', 'ABCDE... Aleatório'), 'ASDFG... Aleatório'))
//...
HMAC(HMAC('3', 'ABCDE... Aleatório'), 'ASDFG... Aleatório'))
As you've noticed, this will be sequential. This indicates that the session will always increment, the last access of the user is in our "State", so to destroy the previous sessions just do Estado -1
and we will get the identifier of the previous session.
The second HMAC, with an application key, is intended to prevent anyone from predicting / recovering even if they have seed access from other users.
In practice:
const ChavePrivada = '...'; // Define uma chave SEGURA de 512 bits.
function calcularSessao(string $semente, int $estado) : string {
return hash_hmac('sha512',
hash_hmac('sha512', $estado, $semente, true),
ChavePrivada);
}
function encerrarSessoesRecentes(string $semente, int $estado) {
for($i = ($estado - 6); $i < $estado; $estado++){
unlink('/tmp/sess_' . calcularSessao($semente, $i));
}
}
Then to set the user session:
mysqli_begin_transaction($link);
mysqli_autocommit($link, false);
mysqli_query($link, 'SELECT ..., Semente, Estado FROM ... WHERE ... FOR UPDATE');
//...
if($SenhaCorreta){
encerrarSessoesRecentes($Semente, $Estado);
mysqli_query($link, 'UPDATE ... SET Estado = Estado + 1 WHERE ...');
if(mysqli_affected_rows($link) !== 1){
mysqli_rollback($link);
exit();
}
mysqli_commit($link);
session_id(calcularSessao($Semente, $Estado));
session_start();
//...
}
I will improve and test the example later, and update the answer, but I believe you can understand.
/! \ Caution:
This was not developed by any security professional. He may have other problems that I have not been able to identify, so there are other attacks that will be successful. If you find one please comment .