How to track anonymous users with Flask
Asked Answered
R

2

6

My app implements a shopping cart in which anonymous users can fill their cart with products. User Login is required only before payment. How can this be implemented?

The main challenge is that flask must keep track of the user (even if anonymous) and their orders. My current approach is to leverage the AnonymousUserMixin object that is assigned to current_user. The assumption is that current_user will not change throughout the session. However, I noticed that a new AnonymousUserMixin object is assigned to current_user, for example, upon every browser page refresh. Notice that this does not happen if a user is authenticated.

Any suggestions on how to circumvent this?

Rube answered 30/4, 2015 at 7:44 Comment(0)
R
9

There is no need for a custom AnonymousUserMixin, you can keep the shopping cart data in session:

  • anonymous user adds something to hist cart -> update his session with the cart data
  • the user wants to check out -> redirect him to login page
  • logged in user is back at the check out -> take his cart data out of the session and do whatever you would do if he was logged in the whole time
Rosenberg answered 30/4, 2015 at 8:6 Comment(0)
J
4

You can use a AnonymousUserMixin subclass if you like, but you need to add some logic to it so that you can associate each anonymous user with a cart stored in your database.

This is what you can do:

  1. When a new user connects to your application you assign a randomly generated unique id. You can write this random id to the user session (if you want the cart to be dropped when the user closes the browser window) or to a long-lived cookie (if you want the cart to be remembered even after closing the browser). You can use Flask-Login for managing the session/cookie actually, you don't have to treat unknown users as anonymous, as soon as you assign an id to them you can treat them as logged in users.

  2. How do you know if an anonymous user is known or new? When the user connects you check if the session or cookie exist, and look for the id there. If an id is found, then you can locate the cart for the user. If you use a subclass of AnonymousUserMixin, then you can add the id as a member variable, so that you can do current_user.id even for anonymous users. You can have this logic in the Flask-Login user loader callback.

  3. When the user is ready to pay you convert the anonymous user to a registered user, preserving the id.

  4. If you have a cron job that routinely cleans up old/abandoned anonymous carts from the database, you may find that an old anonymous user connects and provides a user id that does not have a cart in the database (because the cart was deemed stale and deleted). You can handle this by creating a brand new cart for the same id, and you can even notify the user that the contents of the cart expired and were removed.

Hope this helps!

Jonell answered 2/5, 2015 at 23:48 Comment(2)
Thanks! Is there a way to protect my app from malicious users? Someone could attack by (i) creating a cart, and (ii) closing the session (or deleting the cookie) in a loop. Is there a way to make the cron job (or task queue) help avoid an uncontrolled increase in the database size? Checking the size of the database upon every cart creation is something I would like to avoid.Rube
There isn't something 100% foolproof, but you could keep track of the user's IP address and make sure you don't allow multiple carts for the same one. Or you could write the creation date to all carts, and when you need to create a new one run a query to find out how many carts you created in the last N minutes. If you find that is a large number you can stop creating new carts.Jonell

© 2022 - 2024 — McMap. All rights reserved.