I'm developing a website which have many products. For every product I want to show a counter with the number of different users whom watched it.
I'm facing with the problem that there will be users logged in and others not, and that fact to avoiding to increment a 'watch' more than one time from the same user.
So, what's the best way to tackle this? How do I store the info?
This simply cannot be done for non-registered users. The closest thing you can do and in fact what web analytics services do in practice is to create a tracking cookie.
In its simplest form it looks something like this:
<?php
if (isset($_COOKIE["trackingId"])) {
$uid = $_COOKIE["trackingId"];
} else {
$uid = uniqid();
setcookie("trackingId",$uid,2147483647);
}
Note that analytics sites will attempt to use information which may uniquely identify a user such as hardware capabilities which they receive, screen resolution etc.
Create a table:
Watched by users
productId, userId, trackingId
You can use this table to keep track of who's watching your product. Normal registered users will be stored with a userId. Non-registered users will be stored with their tracking id.
The advantage of this approach is that you can keep track of the same user using the same browser across sessions even if they change IP. The disadvantage is that as soon as the user clears their cookies you've lost this information.
You can refine your tracking mechanism by doing something like canvas fingerprinting instead of using uniqid but the thing to realise here is that there's no method which can uniquely identify a user forever and rightly so because a user should have the right to not be tracked.
For the simple solution, you can:
To separate "view" users, you can count on user's IP.
"View" info can be stored in a simple table product_view(id, product_id, view_ip, user_id)
Related
I'm currently working on my Referral System, but I have a problem with protecting it of frauds.
Okay, here's how it works for now:
user registers and activate it's account
user now have access to the control panel and there is it's uniqe link in following format: domain.tld/ref/12345
when someone other click to user's link, he or she must to click a specific button to confirm that is not some kind of fraud (like "click here, you'll get $100" or something)
system writes visitor's IP in a database and some data to cookies to prevent re-pressing the button. User now have +1 point.
But, the problem is that visitor can change it's IP, clear cookies and hit button again. It takes a few seconds, and that's not OK, that's cheating.
How to prevent it? Is there some trick to get some unique computer ID or something can't be changed that easy?
Really the only options are to tie the process to something which is not so easily manipulated by the user - super cookies, browser fingerprints, OpenID, Email addresses and telephome numbers (the latter 2 using some sort of validaton step before a vote is counted)
The only way you can be certain a referred party does not reuse a referral code is for the original user to send different one-time-use-only referral URLs to each person. Once the code has been used, it is flagged as such in (or removed entirely from) your database so that it can not be used again.
How you prevent the original user from sending multiple links out to the same person is another matter - and not an easy one to resolve.
Who do you perceive to be the threat?
Although it's certainly not 100% accurate, you can still fingerprint visitors using for example a combination of their ip, browser user agent, and with some javascript you can even go for screen size or installed fonts. Using these pieces of information you can set up a system where you save the fingerprints in datatable and in the same record you store the session id (from the cookie). Now when a new visitor arrives you can test their fingerprint against the db of recent fingerprints with different visitor ids. If you find a large number of matching fingerprints (you define the threshold) with different sessions then you can alert for the possibility of fraud.
Cheers
How about storing the link with with the user when they navigate to the link. then in the database you will have the link and if the users has already been to the link then deny them. Seems like it could work then you wouldn't have to worry about the cookies etc...
I want to set up a voting system which doesn't require people to log in, but they can vote as they want.
How do i stop people from spamming on voting (sending request to add the vote)? i know using client site scripting can easily stop it (from proper user), but what about server side (PHP). i don't want people to have that url and constantly hit it to increase the number.
Cheers
Implement reCAPTCHA - it's super easy to implement (takes maybe 10 minutes), is a good anti-spam measure, and serves a greater purpose (digitising books).
If you really want to go with cookies, have a look into evercookies. They're super-invasive, and very unethical, but hey, it's your site :)
You'll have to log their IP and/or set a cookie. The problem with cookies is the client can erase them and the problem with IP tracking is it can block more than one user if a NAT firewall is in the mix, but it will do well for the most part.
You can add a vote_tracking table:
vote_tracking
id
poll_id
session_id
When a user votes in a specific poll, you can update the row with their session id.
You will then need to implement some code to ensure you don't keep issuing queries to determine if user already voted in a poll. If you have an 'active' poll, you can do one lookup, then register a session var indicating that they have already voted, so no matter how many times the poll is rendered, you won't keep hitting the database. Obviously this will only work as long as the current session_id matches, when it differs you will have to issue the first query then reset the session var.
And I'd recommend a reaping mechanism so your table doesn't end up with a million+ rows. If you create a new 'active' poll, truncate the vote_tracking table, or archive it by renaming the table.
Also, the problem with IP tracking is that you will bork users who are behind a proxy, after the first person votes none of the others will be able to vote.
I have some questions about database design for user tracking (analytics)
My website will have 3 classes of user:
non user
user with incomplete regstration progress
registered user
For each of these classes I have different events I want to track. Ie: for a non-user I want to track if they reach registration. For registered I want to track if they make it to a certain page etc...
At the start of each visit I will record their landing page and referrer, then I want to track each of these funnels. So for the table design I am thinking:
A table with their session id (stored in a cookie) and user id if they ever log in=one row per user + one row per guest
A table for visit details- referrer, landing page, time etc... so If a user from table 1 visits 10 times they will have 10 entries in this table. Maybe have another table with a list of browsers?
3 tables for each of the user types with tracking flags. Each row will link to the visit in table 2. So there is a 1:1 relation between these 3 tables and table 2
Is this a logical design for tracking users? Does anyone have any links with good articles on user tracking?
Also, how reliable is the http-referrer header for tracking where users came from? Is there any other method I can use to see where people came from?
Also also, how scalable will this table design be?
Thanks, M
Not having done that before, I find your approach not bad - propably improvable, but ok. Just wanted to add that - depending on your requirements - you could be very lazy and let Google Analytics do that for you!
With different tracking rules, you can set up Google Analytics to track differently depending on user cookies, which you can set in the registration/login-process (or not for the non-user).
Downside of this idea is that you'd rely on javascript and you won't have seperate data for each user, just a total of the user-class.
Here's the GA Resource how to set up exceptions (see the lower description). Then create three different GA tracking codes and on each only accept user with either no-cookie, logged-in cookie or registration-process cookie.
Hope I could help, anyway good luck!
Whats the best way to keep track of how many users and guests are online? Im making a forum for fun and learning
Right Now I have a 2 fields in the users table called is_online and last_access_time.
If current time is 5 minutes or more than last_access_time i set is_online it to zero. And if the signed in user refreshes browser i set it to 1.
But what about guests? I wanna keep track on how many guests are on also
Another thing that would be really cool is to show what page the user is viewing. and on the page, forum thread for example, 5 guests, Homer and Shomer are viewing this page. But how should i structure this? Hmm maybe i should make another question for that.
i dont know what i should do
What do you suggest?
I'd use cookies for this. Set a cookie when the user enters (checking first to make sure one doesnt exist). Easy way to generate a unique id for that user is to hash their IP plus the current time.
$id = md5($_SERVER['REMOTE_ADDR'] . time());
Store that id in your database and use that to reference
You can check what page they are viewing by grabbing either $_SERVER['PHP_SELF'] or $_SERVER['REQUEST_URI'] near the top of your php source. Store that in the table. I'd take a look at php.net's explanation of whats stored in the _SERVER global, as it should help out quite a bit if you find that you need more then just the document they are on (ex index.php). Found here.
You may need to pull apart of the query string that was used to access that page, parse out the variables to determine the page they are requesting. Either way, this could all be done through cookies, or just use a single cookie to store the unique id and use your table for storing everything else.
You cannot know for certain which page a user is viewing, but you can keep track of which page they last viewed. Every time you deliver a page to a user, record that page's path in a database row associated with them. Voila.
To keep the number of guests, I suggest tracking the number of distinct unauthenticated IP/HTTP-User-Agent combinations seen on a certain page in the last X minutes.
I found this article on Web Monkey that might help you.
http://www.webmonkey.com/2010/02/how_many_users_are_on_your_site_right_now/
Sort of a methods/best practices question here that I am sure has been addressed, yet I can't find a solution based on the vague search terms I enter.
I know starting off the question with "Fast and easy" will probably draw out a few sighs, so my apologies.
Here is the deal.
I have a logged in area where an ADMIN can do a whole host of POST operations to input data relating to their profile. The way I have data structured is pretty distinct and well segmented in most tables as it relates to the ID of the admin.
Now, I have a table where I dump one type of data into and differentiate this data by assigning the ADMIN's unique ID to each record. In other words, all ADMINs have this one type of data writing to this table. I just differentiate by the ADMIN ID with each record.
I was planning on letting the ADMIN remove these records by clicking on a link with a query string - obviously using GET. Obviously, the query structure is in the link so any logged in admin could then exploit the URL and delete a competitor's records.
Is the only way to safely do this through POST or should I pass through the session info that includes password and validate it against the ADMIN ID that is requesting the delete?
This is obviously much more work for me.
As they said in the auto repair biz I used to work in... there are 3 ways to do a job: Fast, Good, and Cheap. You can only have two at a time. Fast and cheap will not be good. Good and cheap will not have fast turnaround. Fast and good will NOT be cheap. haha
I guess that applies here... can never have Fast, Easy and Secure all at once ;)
Thanks in advance...
As a general rule, any operation that alters state (whether its session state, or database state) should use POST. That means the only 'safe' SQL operation you can perform with GET is SELECT. Even if you're only using a back-end admin thing, you shouldn't use get. Imagine re-opening your browser and finding that the last time you closed firefox was on your 'DELETE EVERYTHING' GET->delete page resulting in everything being deleted again.
One of the main reasons for this is preventing cross-site request forgeries. For example, if you had a page that took a GET variable such as http://example.com/account?action=logout, an attacker could post an image on your site like this:
<img src="http://example.com/account?action=logout" />
and anyone who opened a page containing that image tag would be immediately logged out, even if they were an admin. It would be very annoying to then search through your raw database for that data and remove it.
Although POST operations are 'nearly' as easy to forge, as a general rule with any web security issue, the trade-off is speed/simplicity vs. security, so you're going to have to choose one or the other.
You should have some kind of session set up.
Using POST over GET gets you nothing tangible as far as security is concerned. POSTs can be forged just like GETs.
So assuming once your admin logs in, you've got some kind of identifier in the session, you just leverage that.
Consider something roughly similar to this:
<?PHP
session_start();
if (empty ($_SESSION['admin_id'])) die("Log in, son.");
if (empty($_GET['record_id'])) die("You've got to tell me which record to delete!");
if (! is_numeric($_GET['record_id'])) die("Invalid record ID");
//just to be totally safe, even though we just enforced that it's numeric.
$record_id = mysql_real_escape_string($_GET['record_id']));
$sql = "DELETE FROM table WHERE record_id='{$record_id}' AND admin_id = {$_SESSION['admin_id']}";
mysql_query($sql);
echo "Record was deleted (assuming it was yours in the first place)";
?>
In that example, we're avoiding the "delete someone else's records" problem by leveraging the WHERE clause in the DELETE query. Of course, to be more user friendly, you'd want to first fetch the record, then compare the admin_id on the record to the admin_id in $_SESSION, and if they don't match, complain, log something, throw an error, etc.
HTH
You're saying: "What if Admin 123 access the URL of Admin 321 directly, thus deleting his stuff?" no?
If that's so then, every admin that is logged in should have at least one session with some unique identifier to that admin. If not, he shouldn't be able to be in the admin section in the first place. Can't you just compare the identifier in the URL with the identifier in the session?
If any user, not just an admin, access those 'delete me' URLs he should be identified by a session as the original 'owner' (admin) of that data.