I have many polls on my site, and I want to prevent users from re-voting many times. As far as I know, I can either keep a IP log of visitors, or store cookies. I tried using an IP log into mySQL database, but theres one problem: All visitors behind a router have the same external IP so only one person behind the router can vote on a certain poll.
So now I'm switching my code to use cookies unless there are better solutions. Since there will eventually be hundreds or thousands of polls, and I think there is a 20 cookie limit, how can I store values for each poll? The values can just be binary values, for example poll1=0 if not yet voted, poll1=1 if voted.
Also, if it helps, each poll immediately shows the results using jquery. I'm assuming I can set/modify the cookie in the jquery resonse.
Any ideas? Thanks! (btw, I realize cookies can be deleted)
If you really want to restrict per-user, you need to implement user identification, which means you need user registration, login and session management. Once you have that, it's not at all difficult. Just implement a many-to-many relation between your user records and your poll records with a join record created when a user takes a poll and checked to determine whether they've already taken it.
Trying to implement a limit on the activities of users without implementing a way of really identifying users will never work well.
Even though you may have hundreds of polls, it is reasonable to expect that each user will only vote in a few of those. So you can just have a single cookie with a comma-separated list of poll IDs in which the user has voted.
Of course, cookies don't provide any sort of protection since they can be deleted or tampered with, but they are also the only practical way to store such information and they work well in most cases.
Related
I have a webshop, user will buy something
When the user visit the my web, their data will be saved temporarly in a variable $user as an array
It will be checked when the user buy something, if their balance is more or equal to the things that they want to buy, but the problem arise when there are some users that try to use two browsers to buy things at the same times, their balance just cut once (it should be twice, since they buy it twice using two browsers)
I know I can just update the $user variable before checking, but I will have to run another query to MySQL, and there is many orders ...
Is there any SQL syntax that can be used to prevent this kind of attack?
for checking their balance and make sure it's correct
Based on your current setup (ie using a variable):
Someone using two browser on the same site trying to use up their balance is going to be fairly rare, with most cases someone trying to game your system.
Just finally check their balance at the point of processing the order and if ok allow it, otherwise don't. For those doing it by accident (which is rare), they'll soon realise the error.
An alternative:
It'd be better to check the real data rather than a variable which isn't reliable and has to be forced to be persistent, and as you know not available in different sessions.
I think a better way would be to use some fast centralised persistent storage like Redis (fairly easy to learn, essentially it's an array stored in memory). You can then store their username (or whatever uniquely IDs them) and while they may have different keys across the two browsers, there will be a common unique ID and you can update their credit value in both (all) sessions by searching for the unique ID.
Then whatever browser that user is logged in to will be updated same as other browsers.
Maybe a better idea:
Unless your application needs it, don't let people log in to different browsers/devices. When they try to login, state "already logged in on another place, want to log that one our and log in here?" etc
I am working on a jQuery Mobile Web App where a company will have the ability to message certain groups of users (based on their profile preferences).
I am debating on what is the most efficient way to mark when each user has read the latest messages. I have considered using a session to try and keep track of the last time they opened the messages page, and comparing that to the post times of the messages. I have also considered a table with the message_id and the user_id, marking each one as read when they open the page.
I think both would work, but I am trying to balance the pros and cons. Keeping in a database would allow me to keep a history (especially if i added a timestamp column to know when they read the message), but if it is going to hurt the app performance due to the table size, then it may not be worth it. The app will potentially have 10's of thousands of users.
One thing I should probably mention is that the users may use the app on multiple devices and the app will have very long session times, potentially allowing the user to stay logged in for months. I like the idea that if they read it on one device then it would mark it read on all devices, which may make sessions difficult to work with, right?
Ok, I'm gonna put everything I said in the comments into one solid answer.
Short Answer: You should be using the database to store 'read' notifications
Logic behind it:
It should be a negligable performance hit with decent servers and optimized code (couple of ms max) even with hundreds of thousands of users
It is highly maintainable
You can track it and sync it across devices
Specifically why you shouldn't use sessions
Sessions were designed to store temporary user data (think ram), they're not supposed to log stuff.
You should not be keeping sessions for months. It is highly insecure as it opens up a much larger window for session hijacking. Rather you should be generating a new session each time the app is accessed, and using a different "remember me" cookie or something each time to authenticate them.
Even if you do make your session persist for months, after those months won't the user all of a sudden get a bajillion "unread" notifications?
How to store it in the database
This is called a many-to-many relationship (from the message perspective) OR a one-to-many relationship (from the user perspective)
Table 1: messages
ID, message, timestamp
Table 2: messages_users
ID, user_id, message_id, read
Table 3: users
(Do user business as usual)
I can do one thing, if no problem with one user or 100 of user, you create one column named readUnread with more than 63,999 Characters in which you use put every user your message with 0 and 1 assign like {jeff:0,kevin:1,Sal:0} when read update from 0 to 1 and when you open this on the screen, split it with current user and ";", this will help you (this is the logic which inhance your performance).
So I have been playing around with a forum I am building and have been stuck on one aspect of it for a while, how to track unread posts and notifications without storing loads of data in the database. After looking at some solutions I believe I came up with a solution that may suit my needs but need a set of fresh eyes to point out what I didn't think of. Here is the architecture of my idea.
1) When a user logs in, check for posts made between current time() and last login time().
2) If posts found, add to array, then serialize() array and save to member row in database.
3) Output array to user if not empty.
This way it will only check for unread posts and store on users who actually log in to the forum, instead of taking up unnecessary space holding unread IDs of inactive users. I'm still wondering if this isn't such a good idea since if the user doesn't read posts then the serialization in the database might become too large to manage.
Does anyone see a problem in my way of thinking? If so please let me know.
Don't worry about the space until there's actually a problem. A table storing the post ID (integer) and the user ID (another integer) will be small. Even if you have thousands of posts and thousands of users, you can safely assume that:
a large part of the users will be inactive (one-time registrations to post something and forget the whole issue)
even the active members will not read all the posts, but rather only a (relatively small) part of the ones that are in topics that interest them.
One other thing: don't store unread posts if you really want to minimise space. Store only the last read post in each thread. That's one record per thread per user, and only assuming the user has ever opened the thread.
If the user logs in, but does not read posts, your scheme still marks them as read.
If the user logs in twice at once (as from a desktop computer and an iPad), what will happen?
What is the problem with keeping each user's view of the forum with a flag to indicate whether they read each one? Such a mechanism is obviously useful to expand into upvoting, favorites, etc.
the users registered in a web site will have the possibility to send invitations to the friends. I want to add a daily limit for the number of invitations that a user may send.
Initially I've just added a limit (40) in the php file, but then I thought it would be better to give to the administrators the possibility to change this limit, so I've added this limit in the database. But now every time a user want to send invitations the database will be used. Would this affect the performance?
How would you configure this feature?
TL;DR: just put it in the database. :)
Complete story: It should not be a performance hit. Everything (the user itself, the usernames of the recipient, loads of stuff from your page) will be coming from your database. you shouldn't care.
If you have a REALLY big userbase, and it becomes an issue, I'm sure there are other places to do performance updates (like use memcached for all sorts of stuff). But if you want to "cache" it, I guess you could retrieve it once while loggin in and put it in the session. Use this value to substract and check etc. then ALSO check once against the database (in the background) to make sure there isn't any sort of freakish thing going on for this user. But this can be async, and does not have as big of an impact for the user-experience.
In the rare case the session says it's ok, but the database says it isn't, just send the user an error. The other way around, might need the user to re-login. But it will be rare or even impossible if you implement it correctly :)
It depends a bit on hardware but a 400,000 row table (10,000 * 40) isn't that huge in MySQL standards. I think you'll be fine.
Just make sure that you've built it sensibly and from how you've described it that there's an index on the column that stores the unique invite code.
This is related to preventing webform resubmission, however this time the context is a web-based RPG. After the player defeats a monster, it would drop an item. So I would want to prevent the user from hitting the back button, or keep refreshing, to 'dupe' the item-drop.
As item drop is frequent, using a DB to store a unique 'drop-transaction-id' seems infeasible to me. I am entertaining an idea below:
For each combat, creating an unique value based on the current date-time, user's id and store it into DB and session. It is possible that given a userid, you can fetch the value back
If the value from session exists in the DB, then the 'combat' is valid and allow the user to access all pages relevant to combat. If it does not exist in DB, then a new combat state is started
When combat is over, the unique value is cleared from DB.
Values which is 30mins old in the DB are purged.
Any opinions, improvements, or pitfalls to this method are welcomed
This question is very subjective, there's things you can do or can not do, depending on the already existing data / framework around it.
The solution you've provided should work, but it depends on the unique combat/loot/user data you have available.
I take it this is what you think is best? It's what I think is best :)
Get the userID, along with a unique piece of data from that fight. Something like combat start time, combat end time, etc
Store it in a Database, or what ever storage system you have
Once you collect the loot, delete that record
That way if the that userID, and that unique fight data exists, they haven't got their loot.
And you are right; tracking each piece of loot is too much, you're better off temporarily storing the data.
Seems like a reasonable approach. I assume you're storing the fact that the player is in combat somewhere anyway. Otherwise, they can just close their browser if they want to avoid a fight?
The combat ending and loot dropping should be treated as an atomary operation. If there is no fight, there can't be any dropping loot.
That depends on your game design: Do you go more in the direction of roguelikes where only turns count, and therefore long pauses in between moves are definitely possible (like consulting other people via chatroom, note: in NetHack that is not considered cheating)? Can users only save their games on certain points or at any place? That makes a huge difference in the design, e.g. making way for exploits similar to the one Thorarin mentions.
If your game goes the traditional roguelike route of only one save, turn basement and permadeath, then it would be possible to save the number of the current turn for any given character along with any game related information (inventory, maps, enemies and their state), and then check against that at any action of the player, therefore to prevent playing the turn twice.
Alternatively you could bundle everything up in client side javascript, so that even if they did resubmit the form it would generate an entirely new combat/treasure encounter.