问题
Possible Duplicate:
Detect if PHP session exists
The PHP manual does not seem to provide a means to check whether a given session_id
exists. For example, session_id()
has an optional id
param, but that replaces the existing id
as opposed to doing a lookup a la desired method: session_id_exists(some-id)
Why do I need to check whether a given session_id
exists? Use case is a sports subscription service where password sharing has become a problem. On login I am storing the user's session id in DB and using that to compare against any other existing session id(s) attached to a given userID
.
In order to implement, I need to check whether collected session ids exist in current session (the proof of password sharing being more than one user logged in at the same time).
I assume there's an easy way to achieve this...
回答1:
How about you do something like this at the top of index.php
// Update current userid/session record with current timestamp
mysql_query("UPDATE sessions SET last_activity = CURRENT_TIMESTAMP() WHERE user = '$username' AND sid = '".session_id()."'");
// Search for multiple records with timestamp in the last 20 minutes where user id is the same
$result = mysql_fetch_assoc(mysql_query("SELECT COUNT(*) AS current_sessions FROM sessions WHERE user = '$username' AND last_activity > '".date('Y-m-d H:i:s', time() - 1200)."'"));
if ($result['current_sessions'] > 1) {
// handle duplicates here
}
You may not like this approach as it involves two DB queries at every page load, but it should work and would probably be more efficient than checking the session files.
回答2:
Following CodeCaster's comment:
Instead of checking PHP session IDs, you should, for each user connexion/disconnection & session expiration, maintain a list of currently connected users (along with connection time, IP etc. maybe), for example in a DB table.
Thus you will be able to detect multiple connections with a single account.
You can as well try to create a small script looping over all session files (if you use the default storage), use an 'unserialize()' on it and check if several session files have the same user identifiers (provided that you store them into $_SESSION
)
EDIT: since this should be done for each user connection, the DB table approach (like what CodeCaster suggests) seems better.
回答3:
You should create your own Session State implementation that offers an interface for the action(s) you need to have for your use-case.
class SessionState
{
public function idExists($id)
{
$gateway = new SessionGateway();
$result = $gateways->searchById($id);
# ...
}
}
If you have implemented the details, you can just use the object(s) within your application.
回答4:
First of all, this has been a nice exploration of ways to prevent password sharing.
My gut reaction to tracking user activity on a per request basis (i.e. the 2 query solution proposed by @DaveRandom) was ahhhhh, no! As @CodeCaster points out, a likely case of premature optimization, but hey, we have a small (few thousand) but rabid user base that will be very click-happy with the start of hockey season and game results coming in. The site has been running snappily for years, don't want to rock the boat, this is a paid service, so performance must be excellent.
OK, the solution:
The apache user has read/write access to the session files in the session directory. By recording session_id at time of login, we have the ingredients to lock down shared password accounts. On successful login:
- Loop through stored session ids related to target account
- if /path/to/session-id-file not empty, increment login counter
- if login counter exceeds number of users allowed for a given plan:
- delete all session files related to target account
- lock the account and force a password reset
There is minimal overhead, the implementation is cake, problem solved.
Note: I had originally thought it was impossible to access the session directory files without creating a security loop; however, that is not the case (at least in my stock CentOS 5 setup). You cannot get a session_id not related to the current user's session, but you can store a given user's session id and access the session file that stores their session from any user's session (including blowing away the file). The key is having the session id to lookup the corresponding /path/to/session-file
来源:https://stackoverflow.com/questions/8166676/detect-whether-session-idsome-id-exists