Redis, expiring array items - redis

I'm trying to use Redis for preventing excessive access to a website, here's a plan, I'd have an array of data
IP => (0 => http://, 1 => http://)
However what I need to do is to set an EXPIRE tag for each one of those items, i've looked into sets, hashes and many other, however I can't seem to find a way. I was told by server support that it's possible but i'm way too new to redis.
I've found the following example on their website
RPUSH pagewviews.user:<userid> http://.....
EXPIRE pagewviews.user:<userid> 60
However i'd need to know the key, which I can't seem to get or find a way to get. I'm using predis to work with redis. Any help would be appreciated!

The userid comes from your app, not from Redis. It can be:
a logical, unique user name (if users authenticate on your site)
some sort of unique ID assigned to every user and persisted in a cookie (disadvantage: users can delete cookies)
a client IP address (disadvantage: multiple users might use the same IP address from a variety of reasons).

Related

Storing multiple sessions in Memcache for a user

I am storing temporary session tokens in Memcache and it works well. When a user logs into my application they present their credentials and a token is stored in Memcache with a 15 minute TTL and also returned to the user. Each time the user makes a request presenting the token its TTL gets extended. The Memcache key is "user-id-{id}". This means that if a user logs in twice their first session will be invalidated as the token is replaced.
I would like for users to have the ability to have multiple active tokens. The reason I use the "user-id-{id}" key name instead of a randomly generated string is because I want to control the number of active tokens a user has. If I gave them random names a single user could fill up my Memcache DB by generating millions of tokens.
How can I limit them to having, say, 10 active tokens? I considered adding an index like "user-id-{id}-{index}" and then iterating over 1-10 for the index to see if there is an empty space for a token. This feels like a lot of work and has some race conditions. Are there better options for achieving my goal if I want to continue using Memcache?
Keep the same key and store a collection of active sessions. If you do this you'll need to manually manage the TTLs for all but the first entry.

How to limit number of actions performed by an anonymous user in a webapplication

I created a webapplication with no registration required and I need to reasonably limit user's actions such as adding a comment or voting.
I wanted to do it simply by identifying users with their IP addresses, however I learned that these can be easily spoofed. Moreover, sometimes there can be a number of users behind one IP address. Additionally, I did not find 100% reliable way to determine user's IP.
How can one deal with this problem? Are there any other ways to set limits per user? Or maybe IP addresses are "good enough"? If yes, what is the best way to determine it?

How to prevent the overload/overuse on a (web) api endpoint?

Let's say I have a web server up and running with an API endpoint (for example .../post) which allows a user to create something (and save into the database). Someone could use a loop to send a huge amount of requests to that endpoint and the database will end up have rubbish data.
What is considered the best practice to protect an endpoint from being overused/overloaded by someone (hacker) in order to prevent a database overflow?
I would recommend user or IP filtering. Basically, keep a track of every request and if someone exceeds a certain number, do not allow further requests.
You can implement it by your own by keeping a track of the number of requests of every user or IP, or you can use some already build code like Rack attack.
One approach is to distribute API keys such that each API user has their own key to be used like a password, and when you discover one is being abused you could revoke their previous data entries to the system. If you do even a cursory google search for API security, you get lots of useful links (like this one).

Redis newbie - equivalent approach to mysql table

I'm new to Redis and was hoping for a "best practice" solution to implementing the equivalent of a "users" table in a mysql database, for handling users in a web app.
Would I create a users SET in Redis? Or a users database with a SET for each user?
My standard setup for users is a serialized object in a standard key u:userid - this object gets retrieved on each request, and there is never any need to access only one of the properties.
You could also use a hash rather than json for the user properties, but my setup includes everything getting used as strongly typed objects and redis running on a different server from the client, so using json makes it easier to use generic deserialization and minimizes any latency issues.
In addition to the user object itself, you will need an index for any fields you need to use to find a user - for example to allow a user to log in with email address you will need a key e:email => userid. A hash will also work here - the important thing is that you need something that is O(1) to get from an email to a user object.
Sometimes parts of the user data should have their own keys - for example a followers list is a perfect match to a redis set, so is best stored in that form.
It really depends on what you'd want to do with the Users within your application. Another option would be to have each user be it's own hash, where they keys are properties (fields) for each user (firstName, lastName, etc). You could use a key that you increment as the ID generator for inserting, and potentially another set that you use to hold all of the user IDs.

Best way to seamlessly & silently authenticate with a second webapp while logged in to a first?

Third party app (A) needs to link users to our app (B) and log them in behind the scenes.
Both apps work independently with their own auth systems. Users share a common unique ID, but have different authentication tokens (username/password/key etc) at each app.
The two complicating factors are as follows:
One app B user may associate with two app A users (e.g. both accounts at app B would redirect and login to the same app A account)
The app B user may not actually have any existing auth tokens, only their personal record and user ID, but we still want to be able to log them in if they are coming from app A.
My first thoughts were OAuth - but I don't think it will work as some users don't have app B accounts and thus won't be able to log in to grant app A access (see point 2 above).
The simplest way I have come up with is:
Each app has a pre-shared key e.g. "LOLS"
Common hash algo generates indepentent identical tokens e.g. hash(PSK + UID)
App B stores hashed tokens for each user
App A sends POST with UID and hashed token to App B, which uses it to identify and auth against a user
The problem with this is that it's hideously insecure. Anyone with knowledge of the pre-shared key (any system admin) and a user's ID (once again, any system admin) would be able to authenticate as ANY user, which is unacceptable.
Does anyone have any solutions? I'd prefer existing standards but am open to customised implementations. We can't really do much to app B other than to get them to use whatever API we provide.
I've faced situation similar to this many times. There have been a variety of solutions we've explored, here's one of them.
You produce a webservice for them to call. This could be something you lock down however you like, including by limiting access to their IP address at the firewall. They post the UID to your webservice, which inserts into a table on your end and hands back some sort of random token (we randomly generated a guid). Your table associates the token with the UID (in plaintext) they sent and a datestamp.
Their application sends the random token to you instead of the UID, you use it to look up the UID, and use the timestamp to make sure the random tokens are expired after a minute or so. Even if someone looks through your table somehow to get the list of UID's recently attempted, it doesn't let them authenticate unless they can pull it off real fast!