I recently went through a live training session, and some videos involving Grails. I was surprised to see that bulk assignment to domain objects appeared to be common practice in the training materials. In other words, account.properties = params
appeared to be the idiomatic way to update a domain object with new values from a web request. The problem with doing that, of course, is that an end-user can submit whatever form fields they choose, and easily change database fields you hadn’t intended for them to change. Fundamentally, this is the same problem PHP was accused of being very insecure for: In the earliest versions of PHP, form values were automatically bound to global variable, so <input name=”email”> on your webform could easily be referred to as $email in your php code. The register_globals parameter was introduced, set to off by default, and eventually removed entirely in order to deal with the security implications. With the PHP globals, you had to be using a poor programming practice(specifically, not initializing a variable before using it) in order to be affected. With an MVC framework, initializing the fields from the persistent record in the database and then changing any which are submitted is considered a feature.
The obvious solution to this issue is to not use bulk assignment, of course and assign values you wish to update individually, and I mistakenly assumed that would be the case in most instances in real life. Then the other week, GitHub was hacked, and a known mass-assignment vulnerability in Ruby on Rails was the cause. So much for that theory. Assigning values manually can get fairly tedious though, so it’s understandable developers would want some sort of shortcut.
A lazier solution than single assignment would seemingly be to implement some sort of filter, explicitly disallowing certain controllers from updating certain database fields. That’s an okay solution until your data model changes, and you forget to blacklist the new fields your old controller doesn’t need to interact with. So filtering isn’t a stellar idea. Whitelisting fields through individual assignment or some other means would appear to be the best solution.
This is where a little Microsoft style thinking actually comes in handy. In fact, bulk assignment to a view-model in ASP.NET MVC is recommended. In it’s simplest form, a view-model would be an object used by one or more controller actions which encapsulates a domain object and allows writing only to the properties actually available to those actions. Essentially, a whitelist. So adding a bit of MVVM to an MVC framework is a pretty clever way of avoiding a potentially serious security pitfall, but there are other benefits to including a view-model layer:
At first glance, adding a view-model layer to an MVC framework seems superfluous, but the advantages in terms of security and separation of concerns make the endeavor worthwhile.
Just as an FYI, Grails _does_ have better ways to do data binding than just
account.properties = params
.You can use Command Objects to bind data to, which are just like little mini-versions of domain objects, with their own validation.
You can also use the
bindData()
method to bindparams
to an object (a groovy bean, in most cases this will be a Command Object or a Domain Object) and specify a white or black list if desired.I think you can also use Command Objects as more structured ways of passing data to the view (or binding to a form), but I’m not sure this is even needed with the great support Groovy has for basic data structures like Lists and Maps.
That’s true Command Objects are very much like view models. It might still be nice to see some support for wiring up a domain object behind one; nothing a plugin couldn’t easily do for those who prefer to do things that way. I wasn’t aware of bindData though, that looks handy. It’d be good if intro to type courses went into some detail with those. Thanks for your comment!