Re: [Catalyst] Preventing simultaneous logins
On Sat, Jul 26, 2008 at 12:56 PM, Daniel McBrearty <[EMAIL PROTECTED]> wrote: > Thanks Matt, I'll definitely try this when I get round to trying to > solve this issue. > > Where does MyApp::set_athenticated get called from? when the user logs > in? no, that can't be it ... you're way ahead of me here :-) ... > The base is from Catalyst::Plugin::Authentication: http://search.cpan.org/~jayk/Catalyst-Plugin-Authentication-0.10006/lib/Catalyst/Plugin/Authentication.pm#set_authenticated(_$user,_$realmname_) But C::P::Session::PerUser has its own which handles merging the session. -J ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
Thanks Matt, I'll definitely try this when I get round to trying to solve this issue. Where does MyApp::set_athenticated get called from? when the user logs in? no, that can't be it ... you're way ahead of me here :-) ... >> >> 1. checking whether there is an existing session associated this username >> > >> > Session::PerUser ? >> > >> >> I looked briefly at this, but I'm a bit wary because >> C::P::Session::Store::Fastmmap warns against being used with it. What >> is PerUser doing that is special in that respect, and what is a good >> backend for it? >> >> REading the docs for it, it seems like something slightly different - >> keeping the same session in place, even if the user logs in in the >> middle of it, if I understand correctly? > > You want: > > login from elsewhere to log out the same user anywhere else > > It wants: > > any login by the same user "claims" the user's session > > so, if you add in your root auto > > if ($c->user_exists) { > unless ($c->user_session->{sid} eq $c->sessionid) { >$c->logout; >$c->forward('/auth/logged_out'); >return 0; > } > } > > and in MyApp > > sub set_authenticated { > my $self = shift; > $self->next::method(@_); > $self->user_session->{sid} = $self->sessionid; > } > > then you should pretty much be done. > > So far as I can tell, this is perfect for you. You just sometimes get > persistent session data as well (it warns against fastmmap because in the > "persistent session" use case fastmmap is lossy - in yours the lossyness > is irrelevant, you don't care about the persistence feature) > > -- > Matt S Trout Need help with your Catalyst or DBIx::Class project? > Technical Directorhttp://www.shadowcat.co.uk/catalyst/ > Shadowcat Systems Ltd. Want a managed development or deployment platform? > http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ > > ___ > List: Catalyst@lists.scsys.co.uk > Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst > Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ > Dev site: http://dev.catalyst.perl.org/ > -- There's an infinite supply of time, we just don't have it all yet. ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
On Fri, Jul 25, 2008 at 10:27:34AM +0200, Daniel McBrearty wrote: > >> > >> 1. checking whether there is an existing session associated this username > > > > Session::PerUser ? > > > > I looked briefly at this, but I'm a bit wary because > C::P::Session::Store::Fastmmap warns against being used with it. What > is PerUser doing that is special in that respect, and what is a good > backend for it? > > REading the docs for it, it seems like something slightly different - > keeping the same session in place, even if the user logs in in the > middle of it, if I understand correctly? You want: login from elsewhere to log out the same user anywhere else It wants: any login by the same user "claims" the user's session so, if you add in your root auto if ($c->user_exists) { unless ($c->user_session->{sid} eq $c->sessionid) { $c->logout; $c->forward('/auth/logged_out'); return 0; } } and in MyApp sub set_authenticated { my $self = shift; $self->next::method(@_); $self->user_session->{sid} = $self->sessionid; } then you should pretty much be done. So far as I can tell, this is perfect for you. You just sometimes get persistent session data as well (it warns against fastmmap because in the "persistent session" use case fastmmap is lossy - in yours the lossyness is irrelevant, you don't care about the persistence feature) -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
Am 25.07.2008 um 10:27 schrieb Daniel McBrearty: 1. checking whether there is an existing session associated this username Session::PerUser ? I looked briefly at this, but I'm a bit wary because C::P::Session::Store::Fastmmap warns against being used with it. What is PerUser doing that is special in that respect, and what is a good backend for it? REading the docs for it, it seems like something slightly different - keeping the same session in place, even if the user logs in in the middle of it, if I understand correctly? You shouldn't store a session in a store which might lose the session because it runs out of memory. Use a store which stores the session permanently like DBIC. cheers ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
>> >> 1. checking whether there is an existing session associated this username > > Session::PerUser ? > I looked briefly at this, but I'm a bit wary because C::P::Session::Store::Fastmmap warns against being used with it. What is PerUser doing that is special in that respect, and what is a good backend for it? REading the docs for it, it seems like something slightly different - keeping the same session in place, even if the user logs in in the middle of it, if I understand correctly? ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
From: "J. Shirley" <[EMAIL PROTECTED]> > It's fairly simple to track user login now. You can have an automatic > ping from the browser to the server that updates the session time. > Just put it in your template wrappers so you have some simple request > (even something like an action that renders an image, and a javascript > timer that reloads that image every X number of seconds). The javascript code could be avoided, so it is not a problem if the browser is not set to support javascript. If the current user doesn't access a new page in 10 (or 15, 20...) minutes, then his session expires and he could log in again on another computer. If a company has a username for accessing a newspaper, and if an employee of that company accesses the site, he should be able to read the newspaper even if another employee tries to log in. But if the first user doesn't access a new page every 10 minutes, his session should expire and allow the other users to log in, even if he stays logged and doesn't close his browser. > That way you can set your lockout time to a ridiculously low level so > the user doesn't have to wait for the session to clear. If the lockout period is too low, the session might be closed much earlier than it should so it should be set depending on the situation, because the browser might not use Javascript, and the user might not access a new page often enough. > I think the points about the problem are perfectly valid though, it's > a hard problem to solve right, because "right" is very use case > specific and the protocol itself is the problem. Yes of course. But in any case, I think that a new login should not disable a previous login, because any new user will log off a previously logged user. In that case the logged off user will try to log in again and he will logg of the other user and so on, and this will not be very nice... A logged user must stay logged while he actively uses the page. If he doesn't *actively* use the page, his session must be disabled, even if he leaves the browser opened. That's why I think that no javascript should be used to ping the server, but consider it *active* only if he accesses new pages at least from 10 to 10 minutes, or another period, depending on the specific situation. Octavian ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
On Wed, Jul 23, 2008 at 09:47:57PM +0200, Daniel McBrearty wrote: > I'm using Cat with a pretty standard configuration of : > > Catalyst::Plugin::Authentication > Catalyst::Plugin::Session > Catalyst::Plugin::Session::State::Cookie > Catalyst::Plugin::Session::Store::FastMmap > > to handle login and session management. My login code looks like this: > > my $u = $params->{username}; > > if ($c->authenticate( { username => $u, > password => $params->{'password'} > } )){ > my $user = $c->user; > $user->last_login(DateTime->now); > $user->update(); > $c->response->redirect( $forward, 301); > > } else { > # login failed > $c->stash->{login_failed} = 1; > } > > > What I'd like to do is check if this user is already logged in at some > other computer, and deny access if so. I guess that means : > > 1. checking whether there is an existing session associated this username Session::PerUser ? > 2. Being sure that the associated session is cleared when the user hits > 'logout' after logout => { shift->delete_session }; -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
> > It's fairly simple to track user login now. You can have an automatic > ping from the browser to the server that updates the session time. > Just put it in your template wrappers so you have some simple request > (even something like an action that renders an image, and a javascript > timer that reloads that image every X number of seconds). > > That way you can set your lockout time to a ridiculously low level so > the user doesn't have to wait for the session to clear. > True, assuming you can count on javascript to be enabled on the client (you control the client software/settings, or don't care to support users that, either by choice, or cooperate policy can't enable js) and take the extra hits on your server(s) and db/session store for each idle client. Even with web 2.0 around there are still quite a few users that will not run js. > I think the points about the problem are perfectly valid though, it's > a hard problem to solve right, because "right" is very use case > specific and the protocol itself is the problem. Yep, all "solutions" have trade offs. If someone knows one that fits all I would be more then interested in hearing about it. ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
indeed, it is use case dependent. The use case here is a common one, free content, paid content, you don't want users giving their creds to all their friends and using it simultaneously. (It is at best a first order solution, obviously if it becomes obvious that a fair percentage are using the system 24/7, something better is needed (say, bw capping). Not to hard to do, if needed.) As for the other points : 1. hadn't considered people closing the browser, without logging out - thanks. I guess a short session time is needed - say 10 minutes. The idea of pinging using javascript is quite neat, but I dislike the idea of making the server handle say 2 unproductive req's per minute per logged in user. I'd even rather something as ugly a js popup saying "If you close without logging out ..." when the user closes while logged in to that, I think. 2. the issue of someone leaving work with their browser left logged in is pretty insoluble (after all the browser could well be left open, so you still rely on session timeout). If they do it, they have to wait the 10 minutes, or go back to that computer and log out. K-I-S-S ... If you do all that, so that logout will always happen, couldn't you then solve it like this? (There may be a big fat hole in this ... this is hardly my specialist area ...): 1. On successful login (ie good U/P), get last session key for that user which you left in the db last time. 2. Look in the store for that key, see if it has timed out 3. If so, actually log in and write the new key to the db. 4. Otherwise, fail and leave the db alone. 5. On a real actual logout, nullify the key in the db and take it out the session store. That has only one db write per login (and I store last_login time anyhow, so no real increase), and the session store stays out of the db. Regarding volume, well, it's hardly an issue today, but you never know ... thanks for the excellent quality of feedback Daniel -- There's an infinite supply of time, we just don't have it all yet. ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
On 23 Jul 2008, at 21:20, [EMAIL PROTECTED] wrote: This is actually a pretty "hard" problem -- there is no right answer. What if the user clears her browser state while using the site? Leaves the computer and browser on at work then tries to log in at home on a different computer? I agree that it's a hard problem if you do it the original way round that was suggested. However all apps which do that (Facebook as an example) - logging into a new session kills your old one, and this is pretty easy to do (given that you force users to have a cookie and etc). I think you can gain most of the lockdown of 1 session per user if you just track user activity over a X minute period. for instance every time a user hits your app add a record that is attached to the user account in the db (src ip, session number, other relevant info). Then do (either inline or if it is too costly, via cron) a check on those entries that looks for multiple IP/Sessions or whatever you define as multiple users (given that http is stateless there really is no _safe_ definition). If that process detects usage over your threshold, disable (temp or permanent) the account. The same process can clean up entries that are outside of the time window that you want to look at. If you in any way expect your site to scale to high volume, I'd highly recommend avoiding any approach like this. Your 'hit logging' table is going to be really really slow (and have massive contention) if you're doing high volume. Also - these lookups for multiple IPs you're talking about, they're not going to be indexed, right? (Adding a *single* index on a table will reduce your max insert speed by 40-60%). Even if you're cleaning out rows pretty regularly, you're going to seriously grind the IO on the DB system, and the general IO subsystem on your database server (not to mention any replication / binlogs / hot backups & etc that you need), is going to be doing significantly more work than it needs to, meaning that the general amount of headroom you have in the system will be that much reduced... Your session storage could be criticized for the same reasons, but is actually significantly less work for the DB (updating, not inserting and deleting - 1/2 the IO and no index overhead as you're re-writing without changing keys), and can _trivially_ be pushed into memcache at a later date when you need to. The approach recommended above requires a relational model, and so moving it to memcache wouldn't work... All of that said, unless you're looking to scale to multiple Mb/s of traffic, then I'm probably being too paranoid - as jay said already, 'right' here is use-case specific :) Cheers t0m ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
On Wed, Jul 23, 2008 at 1:20 PM, <[EMAIL PROTECTED]> wrote: > "Daniel McBrearty" <[EMAIL PROTECTED]> wrote on 07/23/2008 02:47:57 > PM: > >> I'm using Cat with a pretty standard configuration of : >> >> Catalyst::Plugin::Authentication >> Catalyst::Plugin::Session >> Catalyst::Plugin::Session::State::Cookie >> Catalyst::Plugin::Session::Store::FastMmap >> >> to handle login and session management. My login code looks like this: >> >> my $u = $params->{username}; >> >> if ($c->authenticate( { username => $u, >> password => $params->{'password'} >> } )){ >> my $user = $c->user; >> $user->last_login(DateTime->now); >> $user->update(); >> $c->response->redirect( $forward, 301); >> >> } else { >> # login failed >> $c->stash->{login_failed} = 1; >> } >> >> >> What I'd like to do is check if this user is already logged in at some >> other computer, and deny access if so. I guess that means : >> >> 1. checking whether there is an existing session associated this username >> 2. Being sure that the associated session is cleared when the user >> hits 'logout' >> >> I did a quick search and didn't get anything on the list - any quick >> clues about the easy way to do this, before I start digging into the >> guts of the plugins to see how? >> >> many thanks >> > Daniel, > > This is actually a pretty "hard" problem -- there is no right answer. > What if the user clears her browser state while using the site? Leaves the > computer and browser on at work then tries to log in at home on a different > computer? I think you can gain most of the lockdown of 1 session per user > if you just track user activity over a X minute period. for instance every > time a user hits your app add a record that is attached to the user account > in the db (src ip, session number, other relevant info). Then do (either > inline or if it is too costly, via cron) a check on those entries that > looks for multiple IP/Sessions or whatever you define as multiple users > (given that http is stateless there really is no _safe_ definition). If > that process detects usage over your threshold, disable (temp or > permanent) the account. The same process can clean up entries that are > outside of the time window that you want to look at. > > > > It's fairly simple to track user login now. You can have an automatic ping from the browser to the server that updates the session time. Just put it in your template wrappers so you have some simple request (even something like an action that renders an image, and a javascript timer that reloads that image every X number of seconds). That way you can set your lockout time to a ridiculously low level so the user doesn't have to wait for the session to clear. I think the points about the problem are perfectly valid though, it's a hard problem to solve right, because "right" is very use case specific and the protocol itself is the problem. -J ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
"Daniel McBrearty" <[EMAIL PROTECTED]> wrote on 07/23/2008 02:47:57 PM: > I'm using Cat with a pretty standard configuration of : > > Catalyst::Plugin::Authentication > Catalyst::Plugin::Session > Catalyst::Plugin::Session::State::Cookie > Catalyst::Plugin::Session::Store::FastMmap > > to handle login and session management. My login code looks like this: > > my $u = $params->{username}; > > if ($c->authenticate( { username => $u, > password => $params->{'password'} > } )){ > my $user = $c->user; > $user->last_login(DateTime->now); > $user->update(); > $c->response->redirect( $forward, 301); > > } else { > # login failed > $c->stash->{login_failed} = 1; > } > > > What I'd like to do is check if this user is already logged in at some > other computer, and deny access if so. I guess that means : > > 1. checking whether there is an existing session associated this username > 2. Being sure that the associated session is cleared when the user > hits 'logout' > > I did a quick search and didn't get anything on the list - any quick > clues about the easy way to do this, before I start digging into the > guts of the plugins to see how? > > many thanks > Daniel, This is actually a pretty "hard" problem -- there is no right answer. What if the user clears her browser state while using the site? Leaves the computer and browser on at work then tries to log in at home on a different computer? I think you can gain most of the lockdown of 1 session per user if you just track user activity over a X minute period. for instance every time a user hits your app add a record that is attached to the user account in the db (src ip, session number, other relevant info). Then do (either inline or if it is too costly, via cron) a check on those entries that looks for multiple IP/Sessions or whatever you define as multiple users (given that http is stateless there really is no _safe_ definition). If that process detects usage over your threshold, disable (temp or permanent) the account. The same process can clean up entries that are outside of the time window that you want to look at. ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
On Wed, Jul 23, 2008 at 1:12 PM, Jonathan Rockway <[EMAIL PROTECTED]> wrote: > * On Wed, Jul 23 2008, Daniel McBrearty wrote: >> What I'd like to do is check if this user is already logged in at some >> other computer, and deny access if so. > > I would probably store sessions in the database, and then store the > session ID in the user table at login time (current_session) or > something. Then when they log in again, you can join in the session > row, check the expiration time in that row, and then allow/deny the > login. You can also use that opportunity to delete the session from the > database so that the other machine no longer has a valid session. > > I don't think the file-based session stores provide this much > flexibility, but you could probably hack something similar if you really > needed to. > > Regards, > Jonathan Rockway > > -- > print just => another => perl => hacker => if $,=$" > I agree this is the way to go, and it would be pretty easy to write a Credential that inherits from Password that does the additional check before succeeding. That way your controllers stay thin, and this feature is more easily tuned and configured. -J ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
* On Wed, Jul 23 2008, Daniel McBrearty wrote: > What I'd like to do is check if this user is already logged in at some > other computer, and deny access if so. I would probably store sessions in the database, and then store the session ID in the user table at login time (current_session) or something. Then when they log in again, you can join in the session row, check the expiration time in that row, and then allow/deny the login. You can also use that opportunity to delete the session from the database so that the other machine no longer has a valid session. I don't think the file-based session stores provide this much flexibility, but you could probably hack something similar if you really needed to. Regards, Jonathan Rockway -- print just => another => perl => hacker => if $,=$" ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Preventing simultaneous logins
On Wed, Jul 23, 2008 at 09:47:57PM +0200, Daniel McBrearty wrote: > What I'd like to do is check if this user is already logged in at some > other computer, and deny access if so. I guess that means : > > 1. checking whether there is an existing session associated this username > 2. Being sure that the associated session is cleared when the user hits > 'logout' And what happens if they never hit log out? Or if their browser crashes and then they try and log in again? If you really need this feature, try it the other way around: if someone logs in then you invalidate their first session. -- Bill Moseley [EMAIL PROTECTED] Sent from my iMutt ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/