You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Animesh Jain <an...@itasveer.com> on 2008/09/23 08:22:17 UTC

Guest users - how to handle them

Hi

This is more of a best practice question. I would like to know
recommendations on how to handle guest users in a webapp. Lets say I have an
ecommerce store, where a user is allowed to shop around and add items to
shopping cart without logging in (authz). Now how should I maintain the data
this user generates. In my one of my current apps I have a separate
temp_user table but it ofcourse makes things messy in the sense now my order
table has two types of users, one for orders with logged in users and one
for users who are not logged in.

Should we instead have just one single user table and create an entry for a
guest user in it whenever required. For eg lets say when a user adds
something to the shopping cart then we just create a user entry for this
user in the background with a guest role and log him in and then proceed
with the action. How could this logic be possibly centralized. For eg there
may still be certain actions that require a higher role. For eg we may want
payments to be made only after signups. Any suggestions? Also wouldn't this
add a lot of temporary user rows to the user table ?

Thanks in advance
Animesh

Re: Guest users - how to handle them

Posted by Les Hazlewood <le...@hazlewood.com>.
So, what you can do is have the Order link to a Sessions table - to
indicate in which session the order was created.

JSecurity supports this scenario too - you can set a SessionDAO
implementation on the SecurityManager so calls to subject.getSession()
returns a Session implementation that talks to your database.

But since sessions are in the database - you _really_ want to think
about using a distributed/clustered cache like TerraCotta or
Coherence.  Constant serialization of Session objects to/from a
Sessions RDBMS table is the least performant mechanism, so you'd want
that cache enabled.  JSecurity supports this too ;)
(securityManager.setCacheManager(...)).

Cheers,

Les

On Tue, Sep 23, 2008 at 2:56 PM, Animesh Jain <an...@itasveer.com> wrote:
> Hmm.. well yeah I guess its not too difficult to save to the session. But if
> you think of it in a little more detail it can get tricky in certain
> situations. Just for an eg. lets say we delete a product, or it goes out of
> stock or something. If things are in the db then I can make changes across
> the application. This is just an example, maybe not good enough to get my
> point across, but I hope you can see what i mean :). I can think of a few
> other situations (specific to my usecase) where things will really start
> making all the session handling messy.
>
> I'm still thinking, still not convinced with any solution so far. I guess
> this is outside jsecurity anyway.
>
> Cheers
> Animesh
>
> On Wed, Sep 24, 2008 at 12:12 AM, Les Hazlewood <le...@hazlewood.com> wrote:
>>
>> Its _much_ easier to put it in the session ;)
>>
>> subject.getSession().putAttribute( "currentOrder", shoppingOrder );
>>
>> Then you pull it out after they've created an account.
>>
>> It would only make sense to store it in a table if it is persistent
>> beyond the life of the user's session.  But, keying it off of session
>> id won't work - if their session expires and they come back tomorrow,
>> they'll have a new session ID, and the old order would be lost.  It
>> would effectively be an orphan at that point and you'd need a nightly
>> task (e.g. via Quartz) to delete those orphans.  If you want it to be
>> persistent across sessions and they're not a user (a guest), then
>> serialize the order into a cookie.  JSecurity does this for identity
>> serialization for RememberMe.  Check out the WebRememberMeManager
>> implementation for ideas:
>>
>>
>> http://jsecurity.svn.sourceforge.net/viewvc/jsecurity/trunk/src/org/jsecurity/web/WebRememberMeManager.java?revision=886&view=markup
>>
>> Cheers,
>>
>> Les
>>
>> On Tue, Sep 23, 2008 at 2:34 PM, Animesh Jain <an...@itasveer.com>
>> wrote:
>> > oops.. i meant authc too.
>> >
>> > well thats actually what i was trying to avoid. here I'll have to write
>> > separate logic to handle all that data in the session. might as well be
>> > a
>> > separate order table with session id in place of user id. Or is it
>> > easier to
>> > do the handling in session than I'm imagining?
>> >
>> > Cheers
>> > Animesh
>> >
>> > On Tue, Sep 23, 2008 at 11:50 PM, Les Hazlewood <le...@hazlewood.com>
>> > wrote:
>> >>
>> >> Hi Animesh,
>> >>
>> >> (just a quick clarification - we use the abbreviation 'authc' for
>> >> AuthentiCation (identity verification and login) - and 'authz' for
>> >> AuthoriZation (access control - roles, perm checks).
>> >>
>> >> Anyway - on to the question.
>> >>
>> >> In my commerce applications, a user has one or more Orders.  You can
>> >> think of an Order as a ShoppingCart if you like, but I call it an
>> >> Order because it will actually be inserted into the database -
>> >> ShoppingCarts are usually thought of as temporal by nature - i.e. they
>> >> often 'expire' after the user logs out or their session expires.
>> >>
>> >> My Order objects have the following attributes (slightly simplified
>> >> for this example):
>> >>
>> >> - User user - the user responsible for creating/initiating the order.
>> >> - Date creationTimestamp - when the selects their very first item, an
>> >> order is created.
>> >> - Amount subtotal - the total of all the order line items.  An Amount
>> >> object holds 3 things: A currency indicator and a BigDecimal.
>> >> BigDecimal is used to ensure accuracy is retained during currency
>> >> conversion so money is not lost (i.e. a double wouldn't be a good
>> >> choice to represent monetary values).
>> >> - Amount total - the total amount the user owes (includes the subtotal
>> >> plus any taxes and shipping and handling).
>> >> - List<LineItem> - all the line items in the order.  A LineItem
>> >> contains 3 things: a Product reference (what they are buying), an
>> >> Amount - what the price is of the product at the time their selection
>> >> goes into the order (important!), and an int quantity - how many of
>> >> those products at that price they're ordering in the current order.
>> >> - OrderState state - an ENUM representing the current state the order
>> >> can be in - open (i.e. new or continued), paid, shipped, received,
>> >> etc. - whatever your domain needs.
>> >> and a List<Payment> - all the payments associated with the order.
>> >> Most orders will have a single payment equal to the Order total, but I
>> >> model it this way to handle edge cases in my domain logic.  Anyway,
>> >> moving on...
>> >>
>> >> So, how do I handle the scenario of user vs. non user shopping?
>> >>
>> >> If they are a User, the order immediately gets placed in the database
>> >> table as soon as it is created (i.e. they select their first item to
>> >> put in the 'cart' - the Order).  The Order table has a User reference
>> >> that records who is 'building' the order.  The User property is
>> >> non-null for that table, ensuring that all orders are attributed to a
>> >> User.  The interesting thing about this is that a User can have one or
>> >> more open orders - think of any Order that is not their latest
>> >> (current) one as a 'wish list' order that they can resolve when they
>> >> want.
>> >>
>> >> If they are *not* a User, that is, a guest, the Order object gets
>> >> attached to their session.  When they check out, they must first
>> >> create a user account (which amounts to usually just an email address
>> >> and password).  After that is done, the Order attached to their
>> >> session gets added to the Orders table since there is now a User to
>> >> associate it with.  Before they become a User, you can can also
>> >> serialize their Order to a Cookie so if that person does not check out
>> >> (meaning they won't become a User yet), then at least the order is
>> >> there for reconstitution when they come back to the site and they can
>> >> keep shopping with it.
>> >>
>> >> You can check to see if they are a 'User' in JSecurity by checking:
>> >>
>> >> if ( subject.getPrincipal() != null ) {
>> >>    // they are a User because a principal is an identifying attribute,
>> >>    // and you only have an identity if you have an account
>> >> }
>> >>
>> >> Similarly, you can check if they are a 'guest':
>> >> if ( subject.getPrincipal() == null ) {
>> >>    // guest user, attach to session
>> >> }
>> >>
>> >> I hope that helps a little.  Feel free to ask more questions ;)
>> >>
>> >> Cheers,
>> >>
>> >> Les
>> >>
>> >> On Tue, Sep 23, 2008 at 2:22 AM, Animesh Jain <an...@itasveer.com>
>> >> wrote:
>> >> > Hi
>> >> >
>> >> > This is more of a best practice question. I would like to know
>> >> > recommendations on how to handle guest users in a webapp. Lets say I
>> >> > have an
>> >> > ecommerce store, where a user is allowed to shop around and add items
>> >> > to
>> >> > shopping cart without logging in (authz). Now how should I maintain
>> >> > the
>> >> > data
>> >> > this user generates. In my one of my current apps I have a separate
>> >> > temp_user table but it ofcourse makes things messy in the sense now
>> >> > my
>> >> > order
>> >> > table has two types of users, one for orders with logged in users and
>> >> > one
>> >> > for users who are not logged in.
>> >> >
>> >> > Should we instead have just one single user table and create an entry
>> >> > for a
>> >> > guest user in it whenever required. For eg lets say when a user adds
>> >> > something to the shopping cart then we just create a user entry for
>> >> > this
>> >> > user in the background with a guest role and log him in and then
>> >> > proceed
>> >> > with the action. How could this logic be possibly centralized. For eg
>> >> > there
>> >> > may still be certain actions that require a higher role. For eg we
>> >> > may
>> >> > want
>> >> > payments to be made only after signups. Any suggestions? Also
>> >> > wouldn't
>> >> > this
>> >> > add a lot of temporary user rows to the user table ?
>> >> >
>> >> > Thanks in advance
>> >> > Animesh
>> >> >
>> >> >
>> >
>> >
>
>

Re: Guest users - how to handle them

Posted by Animesh Jain <an...@itasveer.com>.
Hmm.. well yeah I guess its not too difficult to save to the session. But if
you think of it in a little more detail it can get tricky in certain
situations. Just for an eg. lets say we delete a product, or it goes out of
stock or something. If things are in the db then I can make changes across
the application. This is just an example, maybe not good enough to get my
point across, but I hope you can see what i mean :). I can think of a few
other situations (specific to my usecase) where things will really start
making all the session handling messy.

I'm still thinking, still not convinced with any solution so far. I guess
this is outside jsecurity anyway.

Cheers
Animesh

On Wed, Sep 24, 2008 at 12:12 AM, Les Hazlewood <le...@hazlewood.com> wrote:

> Its _much_ easier to put it in the session ;)
>
> subject.getSession().putAttribute( "currentOrder", shoppingOrder );
>
> Then you pull it out after they've created an account.
>
> It would only make sense to store it in a table if it is persistent
> beyond the life of the user's session.  But, keying it off of session
> id won't work - if their session expires and they come back tomorrow,
> they'll have a new session ID, and the old order would be lost.  It
> would effectively be an orphan at that point and you'd need a nightly
> task (e.g. via Quartz) to delete those orphans.  If you want it to be
> persistent across sessions and they're not a user (a guest), then
> serialize the order into a cookie.  JSecurity does this for identity
> serialization for RememberMe.  Check out the WebRememberMeManager
> implementation for ideas:
>
>
> http://jsecurity.svn.sourceforge.net/viewvc/jsecurity/trunk/src/org/jsecurity/web/WebRememberMeManager.java?revision=886&view=markup
>
> Cheers,
>
> Les
>
> On Tue, Sep 23, 2008 at 2:34 PM, Animesh Jain <an...@itasveer.com>
> wrote:
> > oops.. i meant authc too.
> >
> > well thats actually what i was trying to avoid. here I'll have to write
> > separate logic to handle all that data in the session. might as well be a
> > separate order table with session id in place of user id. Or is it easier
> to
> > do the handling in session than I'm imagining?
> >
> > Cheers
> > Animesh
> >
> > On Tue, Sep 23, 2008 at 11:50 PM, Les Hazlewood <le...@hazlewood.com>
> wrote:
> >>
> >> Hi Animesh,
> >>
> >> (just a quick clarification - we use the abbreviation 'authc' for
> >> AuthentiCation (identity verification and login) - and 'authz' for
> >> AuthoriZation (access control - roles, perm checks).
> >>
> >> Anyway - on to the question.
> >>
> >> In my commerce applications, a user has one or more Orders.  You can
> >> think of an Order as a ShoppingCart if you like, but I call it an
> >> Order because it will actually be inserted into the database -
> >> ShoppingCarts are usually thought of as temporal by nature - i.e. they
> >> often 'expire' after the user logs out or their session expires.
> >>
> >> My Order objects have the following attributes (slightly simplified
> >> for this example):
> >>
> >> - User user - the user responsible for creating/initiating the order.
> >> - Date creationTimestamp - when the selects their very first item, an
> >> order is created.
> >> - Amount subtotal - the total of all the order line items.  An Amount
> >> object holds 3 things: A currency indicator and a BigDecimal.
> >> BigDecimal is used to ensure accuracy is retained during currency
> >> conversion so money is not lost (i.e. a double wouldn't be a good
> >> choice to represent monetary values).
> >> - Amount total - the total amount the user owes (includes the subtotal
> >> plus any taxes and shipping and handling).
> >> - List<LineItem> - all the line items in the order.  A LineItem
> >> contains 3 things: a Product reference (what they are buying), an
> >> Amount - what the price is of the product at the time their selection
> >> goes into the order (important!), and an int quantity - how many of
> >> those products at that price they're ordering in the current order.
> >> - OrderState state - an ENUM representing the current state the order
> >> can be in - open (i.e. new or continued), paid, shipped, received,
> >> etc. - whatever your domain needs.
> >> and a List<Payment> - all the payments associated with the order.
> >> Most orders will have a single payment equal to the Order total, but I
> >> model it this way to handle edge cases in my domain logic.  Anyway,
> >> moving on...
> >>
> >> So, how do I handle the scenario of user vs. non user shopping?
> >>
> >> If they are a User, the order immediately gets placed in the database
> >> table as soon as it is created (i.e. they select their first item to
> >> put in the 'cart' - the Order).  The Order table has a User reference
> >> that records who is 'building' the order.  The User property is
> >> non-null for that table, ensuring that all orders are attributed to a
> >> User.  The interesting thing about this is that a User can have one or
> >> more open orders - think of any Order that is not their latest
> >> (current) one as a 'wish list' order that they can resolve when they
> >> want.
> >>
> >> If they are *not* a User, that is, a guest, the Order object gets
> >> attached to their session.  When they check out, they must first
> >> create a user account (which amounts to usually just an email address
> >> and password).  After that is done, the Order attached to their
> >> session gets added to the Orders table since there is now a User to
> >> associate it with.  Before they become a User, you can can also
> >> serialize their Order to a Cookie so if that person does not check out
> >> (meaning they won't become a User yet), then at least the order is
> >> there for reconstitution when they come back to the site and they can
> >> keep shopping with it.
> >>
> >> You can check to see if they are a 'User' in JSecurity by checking:
> >>
> >> if ( subject.getPrincipal() != null ) {
> >>    // they are a User because a principal is an identifying attribute,
> >>    // and you only have an identity if you have an account
> >> }
> >>
> >> Similarly, you can check if they are a 'guest':
> >> if ( subject.getPrincipal() == null ) {
> >>    // guest user, attach to session
> >> }
> >>
> >> I hope that helps a little.  Feel free to ask more questions ;)
> >>
> >> Cheers,
> >>
> >> Les
> >>
> >> On Tue, Sep 23, 2008 at 2:22 AM, Animesh Jain <an...@itasveer.com>
> >> wrote:
> >> > Hi
> >> >
> >> > This is more of a best practice question. I would like to know
> >> > recommendations on how to handle guest users in a webapp. Lets say I
> >> > have an
> >> > ecommerce store, where a user is allowed to shop around and add items
> to
> >> > shopping cart without logging in (authz). Now how should I maintain
> the
> >> > data
> >> > this user generates. In my one of my current apps I have a separate
> >> > temp_user table but it ofcourse makes things messy in the sense now my
> >> > order
> >> > table has two types of users, one for orders with logged in users and
> >> > one
> >> > for users who are not logged in.
> >> >
> >> > Should we instead have just one single user table and create an entry
> >> > for a
> >> > guest user in it whenever required. For eg lets say when a user adds
> >> > something to the shopping cart then we just create a user entry for
> this
> >> > user in the background with a guest role and log him in and then
> proceed
> >> > with the action. How could this logic be possibly centralized. For eg
> >> > there
> >> > may still be certain actions that require a higher role. For eg we may
> >> > want
> >> > payments to be made only after signups. Any suggestions? Also wouldn't
> >> > this
> >> > add a lot of temporary user rows to the user table ?
> >> >
> >> > Thanks in advance
> >> > Animesh
> >> >
> >> >
> >
> >
>

Re: Guest users - how to handle them

Posted by Les Hazlewood <le...@hazlewood.com>.
Its _much_ easier to put it in the session ;)

subject.getSession().putAttribute( "currentOrder", shoppingOrder );

Then you pull it out after they've created an account.

It would only make sense to store it in a table if it is persistent
beyond the life of the user's session.  But, keying it off of session
id won't work - if their session expires and they come back tomorrow,
they'll have a new session ID, and the old order would be lost.  It
would effectively be an orphan at that point and you'd need a nightly
task (e.g. via Quartz) to delete those orphans.  If you want it to be
persistent across sessions and they're not a user (a guest), then
serialize the order into a cookie.  JSecurity does this for identity
serialization for RememberMe.  Check out the WebRememberMeManager
implementation for ideas:

http://jsecurity.svn.sourceforge.net/viewvc/jsecurity/trunk/src/org/jsecurity/web/WebRememberMeManager.java?revision=886&view=markup

Cheers,

Les

On Tue, Sep 23, 2008 at 2:34 PM, Animesh Jain <an...@itasveer.com> wrote:
> oops.. i meant authc too.
>
> well thats actually what i was trying to avoid. here I'll have to write
> separate logic to handle all that data in the session. might as well be a
> separate order table with session id in place of user id. Or is it easier to
> do the handling in session than I'm imagining?
>
> Cheers
> Animesh
>
> On Tue, Sep 23, 2008 at 11:50 PM, Les Hazlewood <le...@hazlewood.com> wrote:
>>
>> Hi Animesh,
>>
>> (just a quick clarification - we use the abbreviation 'authc' for
>> AuthentiCation (identity verification and login) - and 'authz' for
>> AuthoriZation (access control - roles, perm checks).
>>
>> Anyway - on to the question.
>>
>> In my commerce applications, a user has one or more Orders.  You can
>> think of an Order as a ShoppingCart if you like, but I call it an
>> Order because it will actually be inserted into the database -
>> ShoppingCarts are usually thought of as temporal by nature - i.e. they
>> often 'expire' after the user logs out or their session expires.
>>
>> My Order objects have the following attributes (slightly simplified
>> for this example):
>>
>> - User user - the user responsible for creating/initiating the order.
>> - Date creationTimestamp - when the selects their very first item, an
>> order is created.
>> - Amount subtotal - the total of all the order line items.  An Amount
>> object holds 3 things: A currency indicator and a BigDecimal.
>> BigDecimal is used to ensure accuracy is retained during currency
>> conversion so money is not lost (i.e. a double wouldn't be a good
>> choice to represent monetary values).
>> - Amount total - the total amount the user owes (includes the subtotal
>> plus any taxes and shipping and handling).
>> - List<LineItem> - all the line items in the order.  A LineItem
>> contains 3 things: a Product reference (what they are buying), an
>> Amount - what the price is of the product at the time their selection
>> goes into the order (important!), and an int quantity - how many of
>> those products at that price they're ordering in the current order.
>> - OrderState state - an ENUM representing the current state the order
>> can be in - open (i.e. new or continued), paid, shipped, received,
>> etc. - whatever your domain needs.
>> and a List<Payment> - all the payments associated with the order.
>> Most orders will have a single payment equal to the Order total, but I
>> model it this way to handle edge cases in my domain logic.  Anyway,
>> moving on...
>>
>> So, how do I handle the scenario of user vs. non user shopping?
>>
>> If they are a User, the order immediately gets placed in the database
>> table as soon as it is created (i.e. they select their first item to
>> put in the 'cart' - the Order).  The Order table has a User reference
>> that records who is 'building' the order.  The User property is
>> non-null for that table, ensuring that all orders are attributed to a
>> User.  The interesting thing about this is that a User can have one or
>> more open orders - think of any Order that is not their latest
>> (current) one as a 'wish list' order that they can resolve when they
>> want.
>>
>> If they are *not* a User, that is, a guest, the Order object gets
>> attached to their session.  When they check out, they must first
>> create a user account (which amounts to usually just an email address
>> and password).  After that is done, the Order attached to their
>> session gets added to the Orders table since there is now a User to
>> associate it with.  Before they become a User, you can can also
>> serialize their Order to a Cookie so if that person does not check out
>> (meaning they won't become a User yet), then at least the order is
>> there for reconstitution when they come back to the site and they can
>> keep shopping with it.
>>
>> You can check to see if they are a 'User' in JSecurity by checking:
>>
>> if ( subject.getPrincipal() != null ) {
>>    // they are a User because a principal is an identifying attribute,
>>    // and you only have an identity if you have an account
>> }
>>
>> Similarly, you can check if they are a 'guest':
>> if ( subject.getPrincipal() == null ) {
>>    // guest user, attach to session
>> }
>>
>> I hope that helps a little.  Feel free to ask more questions ;)
>>
>> Cheers,
>>
>> Les
>>
>> On Tue, Sep 23, 2008 at 2:22 AM, Animesh Jain <an...@itasveer.com>
>> wrote:
>> > Hi
>> >
>> > This is more of a best practice question. I would like to know
>> > recommendations on how to handle guest users in a webapp. Lets say I
>> > have an
>> > ecommerce store, where a user is allowed to shop around and add items to
>> > shopping cart without logging in (authz). Now how should I maintain the
>> > data
>> > this user generates. In my one of my current apps I have a separate
>> > temp_user table but it ofcourse makes things messy in the sense now my
>> > order
>> > table has two types of users, one for orders with logged in users and
>> > one
>> > for users who are not logged in.
>> >
>> > Should we instead have just one single user table and create an entry
>> > for a
>> > guest user in it whenever required. For eg lets say when a user adds
>> > something to the shopping cart then we just create a user entry for this
>> > user in the background with a guest role and log him in and then proceed
>> > with the action. How could this logic be possibly centralized. For eg
>> > there
>> > may still be certain actions that require a higher role. For eg we may
>> > want
>> > payments to be made only after signups. Any suggestions? Also wouldn't
>> > this
>> > add a lot of temporary user rows to the user table ?
>> >
>> > Thanks in advance
>> > Animesh
>> >
>> >
>
>

Re: Guest users - how to handle them

Posted by Animesh Jain <an...@itasveer.com>.
oops.. i meant authc too.

well thats actually what i was trying to avoid. here I'll have to write
separate logic to handle all that data in the session. might as well be a
separate order table with session id in place of user id. Or is it easier to
do the handling in session than I'm imagining?

Cheers
Animesh

On Tue, Sep 23, 2008 at 11:50 PM, Les Hazlewood <le...@hazlewood.com> wrote:

> Hi Animesh,
>
> (just a quick clarification - we use the abbreviation 'authc' for
> AuthentiCation (identity verification and login) - and 'authz' for
> AuthoriZation (access control - roles, perm checks).
>
> Anyway - on to the question.
>
> In my commerce applications, a user has one or more Orders.  You can
> think of an Order as a ShoppingCart if you like, but I call it an
> Order because it will actually be inserted into the database -
> ShoppingCarts are usually thought of as temporal by nature - i.e. they
> often 'expire' after the user logs out or their session expires.
>
> My Order objects have the following attributes (slightly simplified
> for this example):
>
> - User user - the user responsible for creating/initiating the order.
> - Date creationTimestamp - when the selects their very first item, an
> order is created.
> - Amount subtotal - the total of all the order line items.  An Amount
> object holds 3 things: A currency indicator and a BigDecimal.
> BigDecimal is used to ensure accuracy is retained during currency
> conversion so money is not lost (i.e. a double wouldn't be a good
> choice to represent monetary values).
> - Amount total - the total amount the user owes (includes the subtotal
> plus any taxes and shipping and handling).
> - List<LineItem> - all the line items in the order.  A LineItem
> contains 3 things: a Product reference (what they are buying), an
> Amount - what the price is of the product at the time their selection
> goes into the order (important!), and an int quantity - how many of
> those products at that price they're ordering in the current order.
> - OrderState state - an ENUM representing the current state the order
> can be in - open (i.e. new or continued), paid, shipped, received,
> etc. - whatever your domain needs.
> and a List<Payment> - all the payments associated with the order.
> Most orders will have a single payment equal to the Order total, but I
> model it this way to handle edge cases in my domain logic.  Anyway,
> moving on...
>
> So, how do I handle the scenario of user vs. non user shopping?
>
> If they are a User, the order immediately gets placed in the database
> table as soon as it is created (i.e. they select their first item to
> put in the 'cart' - the Order).  The Order table has a User reference
> that records who is 'building' the order.  The User property is
> non-null for that table, ensuring that all orders are attributed to a
> User.  The interesting thing about this is that a User can have one or
> more open orders - think of any Order that is not their latest
> (current) one as a 'wish list' order that they can resolve when they
> want.
>
> If they are *not* a User, that is, a guest, the Order object gets
> attached to their session.  When they check out, they must first
> create a user account (which amounts to usually just an email address
> and password).  After that is done, the Order attached to their
> session gets added to the Orders table since there is now a User to
> associate it with.  Before they become a User, you can can also
> serialize their Order to a Cookie so if that person does not check out
> (meaning they won't become a User yet), then at least the order is
> there for reconstitution when they come back to the site and they can
> keep shopping with it.
>
> You can check to see if they are a 'User' in JSecurity by checking:
>
> if ( subject.getPrincipal() != null ) {
>    // they are a User because a principal is an identifying attribute,
>    // and you only have an identity if you have an account
> }
>
> Similarly, you can check if they are a 'guest':
> if ( subject.getPrincipal() == null ) {
>    // guest user, attach to session
> }
>
> I hope that helps a little.  Feel free to ask more questions ;)
>
> Cheers,
>
> Les
>
> On Tue, Sep 23, 2008 at 2:22 AM, Animesh Jain <an...@itasveer.com>
> wrote:
> > Hi
> >
> > This is more of a best practice question. I would like to know
> > recommendations on how to handle guest users in a webapp. Lets say I have
> an
> > ecommerce store, where a user is allowed to shop around and add items to
> > shopping cart without logging in (authz). Now how should I maintain the
> data
> > this user generates. In my one of my current apps I have a separate
> > temp_user table but it ofcourse makes things messy in the sense now my
> order
> > table has two types of users, one for orders with logged in users and one
> > for users who are not logged in.
> >
> > Should we instead have just one single user table and create an entry for
> a
> > guest user in it whenever required. For eg lets say when a user adds
> > something to the shopping cart then we just create a user entry for this
> > user in the background with a guest role and log him in and then proceed
> > with the action. How could this logic be possibly centralized. For eg
> there
> > may still be certain actions that require a higher role. For eg we may
> want
> > payments to be made only after signups. Any suggestions? Also wouldn't
> this
> > add a lot of temporary user rows to the user table ?
> >
> > Thanks in advance
> > Animesh
> >
> >
>

Re: Guest users - how to handle them

Posted by Les Hazlewood <le...@hazlewood.com>.
Hi Animesh,

(just a quick clarification - we use the abbreviation 'authc' for
AuthentiCation (identity verification and login) - and 'authz' for
AuthoriZation (access control - roles, perm checks).

Anyway - on to the question.

In my commerce applications, a user has one or more Orders.  You can
think of an Order as a ShoppingCart if you like, but I call it an
Order because it will actually be inserted into the database -
ShoppingCarts are usually thought of as temporal by nature - i.e. they
often 'expire' after the user logs out or their session expires.

My Order objects have the following attributes (slightly simplified
for this example):

- User user - the user responsible for creating/initiating the order.
- Date creationTimestamp - when the selects their very first item, an
order is created.
- Amount subtotal - the total of all the order line items.  An Amount
object holds 3 things: A currency indicator and a BigDecimal.
BigDecimal is used to ensure accuracy is retained during currency
conversion so money is not lost (i.e. a double wouldn't be a good
choice to represent monetary values).
- Amount total - the total amount the user owes (includes the subtotal
plus any taxes and shipping and handling).
- List<LineItem> - all the line items in the order.  A LineItem
contains 3 things: a Product reference (what they are buying), an
Amount - what the price is of the product at the time their selection
goes into the order (important!), and an int quantity - how many of
those products at that price they're ordering in the current order.
- OrderState state - an ENUM representing the current state the order
can be in - open (i.e. new or continued), paid, shipped, received,
etc. - whatever your domain needs.
and a List<Payment> - all the payments associated with the order.
Most orders will have a single payment equal to the Order total, but I
model it this way to handle edge cases in my domain logic.  Anyway,
moving on...

So, how do I handle the scenario of user vs. non user shopping?

If they are a User, the order immediately gets placed in the database
table as soon as it is created (i.e. they select their first item to
put in the 'cart' - the Order).  The Order table has a User reference
that records who is 'building' the order.  The User property is
non-null for that table, ensuring that all orders are attributed to a
User.  The interesting thing about this is that a User can have one or
more open orders - think of any Order that is not their latest
(current) one as a 'wish list' order that they can resolve when they
want.

If they are *not* a User, that is, a guest, the Order object gets
attached to their session.  When they check out, they must first
create a user account (which amounts to usually just an email address
and password).  After that is done, the Order attached to their
session gets added to the Orders table since there is now a User to
associate it with.  Before they become a User, you can can also
serialize their Order to a Cookie so if that person does not check out
(meaning they won't become a User yet), then at least the order is
there for reconstitution when they come back to the site and they can
keep shopping with it.

You can check to see if they are a 'User' in JSecurity by checking:

if ( subject.getPrincipal() != null ) {
    // they are a User because a principal is an identifying attribute,
    // and you only have an identity if you have an account
}

Similarly, you can check if they are a 'guest':
if ( subject.getPrincipal() == null ) {
    // guest user, attach to session
}

I hope that helps a little.  Feel free to ask more questions ;)

Cheers,

Les

On Tue, Sep 23, 2008 at 2:22 AM, Animesh Jain <an...@itasveer.com> wrote:
> Hi
>
> This is more of a best practice question. I would like to know
> recommendations on how to handle guest users in a webapp. Lets say I have an
> ecommerce store, where a user is allowed to shop around and add items to
> shopping cart without logging in (authz). Now how should I maintain the data
> this user generates. In my one of my current apps I have a separate
> temp_user table but it ofcourse makes things messy in the sense now my order
> table has two types of users, one for orders with logged in users and one
> for users who are not logged in.
>
> Should we instead have just one single user table and create an entry for a
> guest user in it whenever required. For eg lets say when a user adds
> something to the shopping cart then we just create a user entry for this
> user in the background with a guest role and log him in and then proceed
> with the action. How could this logic be possibly centralized. For eg there
> may still be certain actions that require a higher role. For eg we may want
> payments to be made only after signups. Any suggestions? Also wouldn't this
> add a lot of temporary user rows to the user table ?
>
> Thanks in advance
> Animesh
>
>