How do ViewModels prevent malicious database changes? - c#

While looking at this answer to the question Why do we use ViewModels?, I came across this section:
"A view should not contain any non-presentational logic" and "You
should not trust the View" (because a View could be user-provided). By
providing a Model object (potentially still connected to an active
DatabaseContext) a view can make malicious changes to your database.
What exactly does this refer to? If I have UserId and Password in my Model and my ViewModel, where does the security come in? Some kind of check in the controller? What do we check?
How do we determine we can trust the data from the view? Is this handled by the antiforgery token?

I believe the answer is referring to the over-post problem. When you utilize an entity class directly with your view, and particularly if you save that posted entity directly to your database, a malicious user could modify the form to post fields they should not be able to modify.
For example, let's say you had a form that allows a user to edit widgets. Let's also say that you have row-level permissions, such that a user can only edit widgets that belong to them. So, Joe, our fictitious malicious user, edits a widget he's allowed to edit with id 123. But, he decides he wants to mess with Jane's widget, so he adds a field to the form named Id and gives it the value of Jane's widget id. When Joe then posts the widget form, Jane's widget is updated instead.
A view model is not solely for solving this problem, but it does basically negate the issue because, inherently, you cannot directly save the view model to the database. Instead, you must map the view model's values onto the entity, before saving the entity to the database. As a result, you then explicitly control what does and does not get mapped, so in the same example above, Joe changing the id ends up having no effect because you're not mapping that onto the entity.
In truth, the real problem here is in directly saving anything posted by a user directly to the database. You could actually still feed your entity class to the view as the "model", but then not save the posted instance. Instead, you then create a new instance of the entity or pull an instance from the database fresh, and simply map the values from the posted instance over to that. Again, you wouldn't map a property like Id, so again Joe is foiled. In other words, it's not the view model that solves the problem, it's the never trusting a user enough to directly save anything created via a POST that solves the issue.
Microsoft gives another alternative solution in the form of the Bind attribute, which essentially allows you to include/exclude certain properties on an entity class from the modelbinding process (ignoring any posted values, in other words). So, for example, you could potentially solve the issue above by decorating the param on your action with [Bind(Exclude = "Id")], which would then discard any posted value for Id. However, Bind is horrible for a number of reasons, and you should not actually use it. Always use a view model instead, or simply don't ever directly save the entity instance created by the modelbinder.

Related

How to save it in entity right

Assume i have a big entity and want to create a typical CRUD application. A user shouldn't have the ability to save some fields of my entity.
So i see two ways to implement change-save logic:
a)
Get entity from DB
Out to page with all fields(fields which user shoudnt change outed as hidden inputs)
Take entity by post method
Attach to context and save
In this case i need to out on page useless fields. And it is sucks no doubt.
b)
Get entity from DB
Out to page only necessary fields(fields which user can change)
Take entity by post method
Get entity from DB
Fill DB entity by new values and save
In this case i need to do additional query to DB. So it is not good for perfomance.
What is right way?
or C):
Get entity from DB
Map entity to ViewModel with only the allowed fields
Post ViewModel with data back to controller
Map ViewModel back to Entity
Attach and Save.
EDIT:
I highly recommend AutoMapper for the mapping to and fro
Interestingly enough, I just watched a video made by Julie Lerman in which she discusses almost the exact same problem. Neither of your solutions was what she went with:
Have a separate entity class that contains the fields that you want to go on the screen, but still maps to the same table that the regular one does. Then just query that DbSet for grabbing the entity (with only those fields), and save the updates to that.
She mentioned this while discussing implementing Domain Driven Design on top of Entity Framework. So that if you have different DbContexts for different functions in your application, you can still have a DbContext that you're using write to the table, but you can restrict which fields that context can write to.
It is recommended to use different ViewModels for different tasks. If you want to show the user some fields of the Model to edit, then you can do so using EditModel and while saving use CreateModel to create and populate the database. This way you can avoid your database structure to be known to the user, thus ensuring protection and security.

Model with extra fields

Suppose I have a table with whole bunch of fields and an EF entity generated for it. Suppose I want to show an edit form for this entity, BUT with an extra field that doesn't directly map to the table.
So I create a model class that inherits my entity class and my field to it. So far so good.
The issue is that now I have to copy every single field from the entity object to the model object when returning a view and the other way around when saving data. Surely there is a cleaner way to do this?
Specific example would be a user administration form and extra fields would be password and confirm password fields, which are stored in the Membership table.
It's good practice to separate between data-transfer objects used for communicating between application tiers such as UI, and raw entities connected to the storage. Yes, you'll need to copy fields back and forth, but there are tools that can help you with this task, such as AutoMapper.
You can make the EF entity partial (I think they usually are by default), and then add the field in a separate file which also has a partial class for that class. It's not as good practice as Ilya's answer, but it's easy.

How do I store information in multiple tables when trying to edit a profile, MVC3?

I am currently working on a profile for my website. I am trying to make it so that I can save profile data that is stretched across multiple tables.
For example I have Personal info which is the main User Table. It holds personal information about the user.
Then I have separate tables for the usernames they have, as I will have other information pertaining to the user under that username.
When trying to save the information to my database. I get this error: A referential integrity constraint violation. I have tried making individual forms for this, but I don't see that working. My question is, do I make a HTTPPOST method for each table I want to save data to or can I do it in just 1 POST method?
My question is, do I make a HTTPPOST method for each table I want to
save data to....
You can make an POST for each form you are posting to the server. If the formfields in that form match a domain object (at least the primary key), then you might be able to use your database objects in this way. It depends on how your database objects are constructed.
or can I do it in just 1 POST method?
Yes, create a view model that contains members for all of the formfields on the form. Be sure to include hidden formfields for whatever primary keys you need for database lookups. When you POST, map the view model members to your database object.

What approach to choose for ViewModels?

I am using ViewModels with asp.net MVC3. One of the thing I am curious about is, suppose I have an entity named Customers and it has Add, Edit, Delete screens. Assume that they all have different properties requirements.
For eg. Add may have address field but the edit screen may not have edit screen, delete may only use customer name more than anything else.
My question is, how do you create ViewModels for this? Do you go with the approach of shared ViewModels between add, edit and delete i.e a single viewmodel class that handles all for you or do you prefer to create viewmodels classes / page?
Advantage with shared viewmodel is it reduces development time and we can reuse classes. But big problem with this is that if you are using tool like Automapper you may expected results for different screens.
Disadvantage with one viewmodel/page is that it increases development time. Which way should I go?
My approach to view models is to use shared view models until the requirements (the data transported) to the view is different. That means I'm using a shared view model for example for CreateAddress and EditAddress in case all data transported to the view is the same. In case an additional field needs to be displayed in the view for example in the CreateAddress view I'm refactoring my view models and using different view models for CreateAddress and EditAddress.
For example for DeleteAddress I'd use a distinct view model from start because I know that the data displayed in the DeleteAddress view is almost never the same as in Create/EditAddress.
Another approach is to use dynamic view models, since view models should/must not implement business logic and act as DTOs between controller and view this approach has some benefits (No need to create logic free, throw away DTOs).
It depends upon situation. if you have similar requirements for different screens (validation, properties to render etc.) you can use the viewmodel across different views. If there is difference of one or two properties, i would still use the same viewmodel and where these properties are not needed i will put them in hidden inputs so they travel back with the form post not allowing unwanted results. Hidden fields, as all know, can be tweaked and its upon developer to decide if it is safe to use hidden fields. However, if i have different validation requirements for two screens then i definitely have to go with viewmodel/page approach. You can mix both approaches according to requirements as they say "there is no best way of doing things"
All fields that exists in a model can be changed. It doesn't matter if they are hidden or not. All the user has to do is to inspect your pages and try to figure out what fields exist in the model.
Then he can add those fields (for instance with Chrome Dev Tools) to make changes to them.
The safest way to get rid of that problem is to just have models that only have the fields that are allowed to be changed.
That said, go ahead and use the same model if all fields in the model should be allowed to be changed by all users. (And simply do not show the fields that should not be modified)

Detecting changes on entities in contex of asp.mvc

I have very standart scenario. I send entity from controller to view for user to edit it. User pushes submit button I get entity back from browser in my controller. Its detached now so I attach it back to context. How can I detect if there were changes made compared to database?
You need to pull the entity back from the database when the user submits. There are a number of reasons you can't know for certain what to do just by looking at what came back:
Can't trust data from the user. The user has full control over what the browser sends back to you, so this is a possible exploit if you key off something in the request
Another user might have modified the same data
Pulling an entity from the database is fast, so just pull it, set the fields you want to set and SaveChanges()
Addition: As Eduard noted in the comments below, it looks like there is a utility method ApplyCurrentValues to do this: msdn.microsoft.com/en-us/library/dd487246.aspx

Categories

Resources