Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm going through a MVC tutorial, and I notice that convention seems to be to expose a tables primary key on detail pages/urls (ie. /Movies/Details/5 as an example from the tutorial).

It's obviously not a problem for things like a movie record or a SO post, but it might be a bit different for an invoice or transaction with confidential information on it if the key was sequential or guessable.

So, is it just this tutorial or do MVC apps typically expose a tables primary key? Is there a common library or pattern for hiding the key if you don't want to expose it?

share|improve this question
1  
Note that if your domain allows it you could use a natural key in URLs, just configure your routes and repositories/DAOs accordingly. –  Jeroen Jan 28 '13 at 15:21

5 Answers 5

up vote 3 down vote accepted

And that's why I think those tutorials simplify things to a degree that confuses the newcomer.

Try to do a little "tabula rasa" and think the process from scratch, and decoupling the concepts.

First of all, MVC is a presentation layer. It does not (or should not) even know what is backing it up. It could be a database, an xml file, a text file, an in-memory collection, whatever. It should be abstracted away.

What does MVC understand? Receives an HTTP request, parses it using the route engine, resolves to the corresponding controller/action method and does whatever you write in the action method. End of the story.

Do you ask for an id which, behind the scenes, corresponds to a database surrogate key? MVC doesn't know that. For it, it's just an int parameter of a method.

It's entirely up to you how you decouple your logic and layers, how you retrieve data and check for security.

Assume you get asked for Products/Detail/1. Is your action method under authentication (using the authorize attribute)? If so, are your products only visible to certain users?

You'll pass to a business logic method the requested id along with the username, and that method will tell you "here's your product" or "sorry, you cannot view this" based on the logic inside. And heck, if you designed it well even the business logic method won't know if behind the scenes it used a database or anything else to retrieve the product.

I hope this little explanation clarifies things a little. MVC is just about handling HTTP requests and returning a view or some json data or whatever you want to return to the users. Anything that backs it should be abstracted away and implemented as you see fit.

share|improve this answer
    
+1 for the surrogate key, which is what I was really thinking about and not security. –  jmoreno Jan 29 '13 at 16:33

Displaying the key is totally optional, but it isn't a security issue even if you do. You need to check if the user has access, always. That is your job, not the framework's.

But you don't have to use a numeric id. I like to do something like the content type and title in the url:

/news/title-of-article
/reservations/description-of-hotel-and-reservation
/properties/address-of-property
etc.

I then use that information to find the piece of content. Not for security reasons, the title is only superficially more private than an id, but for usability and/or SEO.

I also like to allow the user to get rid of the slug (title, whatever you want to call it) in the URL and receive exactly what they expect. Again, just usability, not security:

/properties/address-of-property (single property)
/properties (list of properties)

MVC apps often have a default convention of controller/function/id. That is just a default. There is no reason to use it if the URL matters to you. Tutorials will usually teach the defaults, but after the tutorial you can (and should!) learn more. Then change things to match your needs.

In every framework I have worked in, there has been a way to map urls to functions and pass in parameters (whatever part of the url you want). They have, without exception, been called "routes."

Use well thought out routes if you want a more user/search engine frindly url. Or use the defualt if you don't need better urls, but just want to quickly build the app. Either way, check if a user has permission to see something. Always.

Knowing the URL must not equal able to gain access and it is your job to enforce that, no matter what your URL looks like.

share|improve this answer
1  
+1 - its a common and well documented security problem, see owasp.org/index.php/Top_10_2010-A4 –  Qwerky Jan 29 '13 at 10:34

an invoice or transaction with confidential information on it if the key was sequential or guessable.

Even if it's guessable, it shouldn't be accessible. Show something like an "Access Denied" error message. Sequential keys are used because they're simple and don't hold information about their contents.

Security by obscurity (neener neener neener, you can't guess the ID!) is no security.

share|improve this answer
    
In regard to your last sentence, why does not apply equally to passwords or encryption keys? –  Michael Borgwardt Jan 28 '13 at 13:37
1  
@MichaelBorgwardt Because passwords and encryption keys aren't used in a void –  Izkata Jan 28 '13 at 14:10

This is common in tutorials, and even simple apps where record keys aren't sensitive. But MVC doesn't force you to do it that way... If you don't want to use easily guessable sequential IDs, you don't have to.

And to be fair, this doesn't have anything to do with MVC. I can't count how many websites I've seen where the convention is something like /movies/details.aspx?id=5 or /movies/details.php?id=5

share|improve this answer

This is just the standard routing aspect of MVC. Another example would be:

Movies/Details/{parentKey}/{thisKey}

You shouldn't expect MVC to provide any level of security. That is your job. Just because I can guess that there is a key of 5, doesn't mean I should have access to it. Any ActionResult that you feel will reveal sensitive data should have some type of security involved - either in the ActionResult itself or by using an AuthorizeAttribute on the ActionResult (or even on the entire controller class).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.