I have a model in my database whose ‘show’ action is open to viewing at URLs like:
mysite.com/project/12
mysite.com/project/14
The way my system is set up, there are a couple of defined methods through which these should be accessible:
- A custom route I’ve set up is accessible to any visitor (registered or unregistered) who has this route. As an example, this custom route might be
mysite.com/companyname/projectid, which the company might pass out itself to certain people it wants to have access. Note that this custom route runs a separate controller action, which sets some internal analytics then redirects to theshowaction. - Direct access when linked to by a registered user’s home page.
I want to restrict the ability to start with mysite.com/project/14 then simply change the IDs, thereby seeing any project. How can I do this?
Clarification
My goal with this question is not just to obfuscate record IDs to make discovering certain records harder. Instead, I would like there to be only two allowable means of accessing project/12:
- A user clicks on a link we provide on their home page (how can I ensure this link alone reaches project 12?)
- A user or simple visitor is redirected here by another (specific) controller action.
Typing in project/12 directly should not be possible. At the moment, I imagine the best way to do this would be for the two methods above to pass a code that gets picked up by the project#show action. I just don’t know how to implement this and if there are potential drawbacks.
Whatever you come up with – it is going to end up being security through obscurity due to this simple requirement:
What you can do, however, is make it difficult to just straight-up guess the correct URL for the project.
My thought would be to give every Project a unique ‘token’ – If you are not logged in as the owner of the project, then you must use the token to access it.
For instance, in your project model you could have this:
Then, in your project’s show action you would need to have this:
Then the owner of the project can share the ‘public’ link of their project to people they want to have access to it, which would look something like this:
Again, anyone with that url could access the project, and I don’t think you will be able to sanely get away from that – but it makes it a lot more difficult to do so.
This is the same concept many password reset functions work. Anyone with access to the password reset token could reset your password after you’ve requested a password. But knowing what token to use will take you ages (Make the token longer to make it harder to bruteforce).
That personally is how I would handle it, and how I’ve seen this sort of thing handled in the past (photobucket, private gists on github, etc)