first off all please excuse me if i dont use all the right terminology. I have the URL issue with my rails app. Basically it works but I just find the url to be a bit too "obvious" and maybe a security issue.
example i have a user resource the users show page will go to websitename.com/users/user_id right ? This is probably convention but how do i go about changing that to display something random ? I tried using a secure token (not sure if it was the right thing to do) and sessions are saved in the token but the url is still quite obvious. Authorization works and non-signed in users cant just visit lets say user with id one lol. Please if this dosent make sense I will try and clarify just ask. Thanks.
Edit.
Also can some one explain to me what a token does then, my understanding was instead of saving a user session with the user id and the id hets displayed, a users session was saved in a secure token and the token (generally random string) got displayed. wrong??
You can overwrite the to_param method for your user object. You could then have i.e. a column in the database, where you store a hash that is your param for the object. See also the Rails guides section for that.
Try https://rubygems.org/gems/friendly_id
It allows to have permalinks in urls instead of plain IDs
Related
i am using like
def to_param
"#{self.attr1}-#{self.attr2}"
end
and my urls look as I want to, though when I :edit,(editing) the url redirects/goes back to showing the :id.
Im letting guest users change some specific record without logging in sending them through a specific link and I want users to not be able to manually change the url or at least show them a large slug so they can't guess the id.
Thanks in advance for any help, theres many posts around this but can't find a solution to fit my needs.
credit to #Dipak for pointing me in the right direction.
I managed to do it with Friendly_ID gem,
though it gave me some trouble because i had some redirects before the actions and it didn't want to pick up the slugs.
I had my redirects as 'redirect_to mymodel_path'
I finally got it working passing 'redirect_to mymodel_path(mymodel)'
Thanks!
To generalize this question I asked this morning, and please accept my apologies if this has been asked before and I simply don't know what to search for, but I'm curious how Rails handles the following situation:
Using Devise, I log in a user, with an ID of 2.
I click on a link that has been created to "edit my profile" (which simply would go to the /users/2/edit page).
Using Firebug (or something similar), I modify the form and change the action from action='/users/2' to action='/users/5'.
I change an element on the form, and click submit.
At this point, Rails appears to allow the submission and update user with ID 5 with my changes.
I'm guessing I'm not the first one to ask this question. It seems to me like Rails should handle this "out of the box", but I could be wrong. Does Rails handle this natively and I'm just missing something? Has this been asked before on SO or somewhere else that I'm missing?
A few things:
Don't create a route that accepts a DB id. Instead, make it something like /my_profile.
If an id is passed in the params, ignore it entirely in the controller. Instead lookup the current_user that is logged in and show them their own profile regardless of what profile/user id is passed in.
Finally, and possibly most important, use authorization (what a user is allowed to do) in order to disallow one user from editing another user's profile. Not to be confused with authentication (user logins/logouts).
With this approach it won't matter if the DOM is changed, because the server should never implicitly trust what is passed to it, which is the problem you're facing now. Any web/app server must always confirm that the parameters being passed to it are actually valid in the context of what the current user is allowed to do.
This idea that the server should never trust what's passed to it is a critical idea to apply to every single action in your app, without exception.
Guys i'have a question.
I'm currently buiding a wizard that has 5 step's until being completed.
The user starts by the first step where he generates the entry id.
From there on i start passing the id over the url like this:
host.com/{controller}/{view}/{id}
This is how my url looks like after the step1,
------- currently at view step2 passing the id=120
host.com/{controller}/step2/120
This isn't safe because as you know, anyone can change the id and affect other users's entries. Ofc, it can be quickly solved by reading if the authenticated user is proprietary of the entry that he must be trying to access in each view.
Now, my question is... is there a better way to do this?
Any tips for future work?
Is what i'm doing enougth?
(begginer doubt praying for a expert awnser)
Cheers
...It can be quickly solved by reading if the authenticated user is proprietary of the entry that he must be trying to access in each view.
Yes, that's true. You should start there.
Here are some other things that you could do:
You could make your entry ids Guids instead, so that a would-be hacker would never try to guess an entry id.
Because using GET for sensitive data is a bad idea, you could, as endyourif suggests, pass the entry ids with hidden fields instead.
If you are truly concerned about the user altering the ID in the URL, then you must spend the additional time adding an "isOwnedBy" like functionality.
As an additional security measure, you could pass it via a hidden variable in the form so it is at least not as easy to change as well.
Edit: I like #LeffeBrune's suggestion of encrypting the idea as well. However, I still suggest that the validation is performed on the function to ensure the user owns the object. It's just good practice.
I'm designing (and developing) web software that will allow the general public to sign up for a service, become a customer, and exchange fairly sensitive data.
I'm working through the documentation and the tutorials, and of course the RESTful pattern adopted by the default routing in ASP.NET MVC is to do URL's like this: /customer/edit/3487.
I guess I am a little squeamish about displaying such technical details as customer ID in the URL bar.
What do the smart kids do these days? Does RESTful have to mean "put your record ID's on display"?
Edit: In an ASP.NET WebForm I would have stored this in the session, I think. But I'm finding that this is discouraged in ASP.NET MVC.
Edit:
I do not intend to rely on security through obscurity.
That still doesn't mean its a good idea to give the users any ideas, or any information about the underlying data. Let's say I have an app that's publishing information about the different business in a Chamber of Commerce, to be arbitrary. Once you are logged in, you have an administrative right to click on every business in the directory and see them all - but the application is supposed to spoon feed them to you as search results or the like. Just because the user technically is allowed to access all records, this doesn't mean it should be trivial for you to write a screen scraper that downloads all of my content in a few minutes. As well, the user can just look at customer ID's and make a guess about how many customers I might have. There's lots of good reasons not to display this.
As long is there is proper authentication and authorization being done on server side then displaying ids is not an issue.
Otherwise just try to encrypt the particular id or username in the URL, this way it will be difficult for the attacks.
You don't have to put the Id in the Url, you just need to use a unique value or unique combination of values to find the data you want to display.
I'd think that the actual bussinesses name would be good and also look good in the Url. So you would have something like this:
/Business/View/theouteredge/
Or if the business name is not unique you could use a combination of business name and zip/postal code.
/Business/View/theouteredge/78665/
You would have to write a new route to handle this.
routes.MapRoute(
"Bussiness",
"Business/{Action}/{name}/{zip}/",
new { controller = "Business", action = "Index", Name = "", PostalCode = "" }
);
All this action would need to be secured with the [authorize] attribute, or the controller its self.
If you also decorate your actions with [authorise] then if another user does use the id from another user, they will automatically be challenged for a login.
It's 6 of one and 1/2 dozen of the other as to whether you use an ID or a Name. Eventually they both resolve to a record.
The important thing is to only allow authorised persons to view the data by allowing them to log in.
I've got a site which has sensitive data but only if you are the holder of that info can you see it and I do that by decorating my actions and checking rights etc.
I think that putting an ID in a url is fine -- as long as it is a Surrogate Key. The key has no value, except to identify a record. Just make sure that the requester is authorized before you send sensitive data back to the client.
Update:
I can see how having a number as part of your URL is undesirable. After all, a URL for a web app is part of the user interface, and exposing such internal details can take away from the UI's elegance. However, you are faced with limited options.
Somehow, you have to identify the resource that you want to get. The crux of REST (IMO) is that a request to a server for a particular resource must be described entirely by the request. The key for the item you want has to be encoded into the HTTP GET somehow. Your options are: put it into the URL somehow, or add it to a cookie. However, adding a key to a cookie is frowned upon.
If you look at this site you will see the question id in the url. If you view your profile you will see your username. So you would probably want to use usernames intead of an id.
If you're really concerned about it you can use a Guid, which isn't very user friendly but would be very hard to guess. :)
If you use some other way than customer id simply because you're concerned about security, then that means you're using security through obscurity, which is a bad idea. Proper authorization would require something like you either 1) have to be logged in with that customer id, or 2) be logged in as an admin, to have that request succeed.
For a webapp written in Grails I would like to keep track of the current users account. In addition the account-name should be displayed as part of the url.
1) Keep the variable in the session
2) Pass the variable via account parameters
Currently I am experimenting with option 2 which allows me to create URL's like http://app.com/accountname/controller. The drawback is that with every URL I will have to pass the account name along as a variable. This is tedious and error prone.
Is any of the two options preferable? Are there better ways in Grails to achieve this?
Regards,
Jens
I have been using a session variable to keep track of the user's account.
Ie: session.user = userAccount;.
You could set this in your login controller.
A better way to keep track of the user is probably to set a cookie. It will be sent to the server with every request & you can easily read it. Why do you need the account name to be part of the URL? I can't think of a good reason to put the current users account in the URL. What happens when someone copy's & paste a link, and someone else follows it? Can you give some more details on what you're trying to do?