Posted by Tom Moertel
Thu, 16 Jun 2005 16:00:00 GMT
I am delighted to report that the button_to
helper
has been added to the Ruby on Rails
web-development framework. David
applied the patch earlier
today, and so button_to will be in the much-anticipated Rails 1.0
release.
David’s change-log entry summarizes the patch well:
Added button_to as a form-based solution to deal with harmful
actions that should be hidden behind POSTs. This makes it just as
easy as link_to to create a safe trigger for actions like destroy,
although it’s limited by being a block element, the fixed look,
and a no-no inside other forms.
David does a good job of highlighting the helper’s limitations. I’ll
take this opportunity to elaborate on each.
It is a block element
The button_to helper creates a small form, which in HTML is considered
block content, just
like the p, div, and blockquote elements are. Basically, block
content cannot be mixed into runs of text. But links can: links are
inline content. Thus
button_to cannot be used as a drop-in replacement for every
occurrence of link_to that might be unsafe; it works only for those
occurrences within block-accepting contexts.
Luckily for us, when designers use links to trigger unsafe actions,
they rarely slip such links into the middle of ordinary looking
text. Naughty uses of link_to almost always occur within contexts
that accept block content. In Rails-generated scaffolding code, for
instance, the unsafe uses of link_to occur within table cells, and
table cells have a flow content
model, which accepts
both inline and block content. So button_to works great for the
default cases in Rails.
It has a fixed look
As its name implies, button_to creates buttons. Buttons don’t look
like links and aren’t styled the same way that links are. For some
design scenarios, this might be a problem.
(My view is that links should not be used to trigger unsafe
actions. In the same way that action-triggering GET requests violate
the spirit of the HTTP standards, action-triggering hypertext links
violate the spirit of the HTML standards. For this reason, I view this
limitation as a feature.)
It is a no-no inside other forms
Forms cannot be nested, and so button_to cannot be used inside of
forms.
Fortunately, this limitation usually doesn’t matter because when we
are inside of a form, we can use its buttons instead of
button_to-created buttons to trigger actions. Still, there are some
circumstances where it does matter, such as the “Amazon.com wish list”
scenario. In this scenario, we should consider other
options.
The bottom line: Pick the low-hanging fruit
While button_to has its limitations, it does provide a simple solution
to the unsafe-GET problem for most real-world cases. I am glad that it
is now a part of Rails, and I offer a big thank-you to David for
accepting the patch.
Posted in web development, rails
Tags get, gwa, link_to, post, rails, safe, unsafe
no comments
no trackbacks

Posted by Tom Moertel
Sun, 08 May 2005 16:00:00 GMT
As I wrote earlier, it’s time for web developers to do away with the fundamentally broken practice of using hypertext links to trigger dangerous events such as deleting things. One of the first places we ought to clean house is in the burgeoning Rails web-application framework, where this practice is pervasive.
The primary culprit in Rails is the all-too-easy link_to method, which is (presently) the orthodox means of creating links to any action, even unsafe ones. For example:
link_to "Destroy", :controller => 'accounts',
:action => 'destroy', :id => 6
The above code generates the following HTML hypertext link, which when followed will merrily delete account number 6:
<a href="/accounts/destroy/6">Destroy</a>
Because this practice is dangerous and contrary to the decade-old convention that links be safe, the link_to method thoughtfully lets us request that a Javascript confirmation dialog be tacked onto the link for added protection:
link_to "Destroy", ..., :confirm => "Are you sure?"
The resulting “safe” HTML:
<a href="/accounts/destroy/6"
onclick="return confirm('Are you sure?');">Destroy</a>
Unfortunately, the Javascript protection doesn’t work. First, not all web browsers care about it. Lots of people surf with Javascript turned off. Second, a whole slew of things besides web browsers live on the Internet, and almost all of them are oblivious to Javascript. Web crawlers fall into this category. They will be more than happy to follow any link you feed to them. “Hey, Googlebot just deleted every account in our database!” Oops.
Thus another layer of protection is commonly used: authorization. The theory is that dangerous links can be safely corralled in the private parts of a web application, where the public and web crawlers cannot go. Only authorized users can get into those parts, and those users will be smart enough not to click on the truly dangerous links unless they really mean it.
The problem is, any number of intermediary agents can be operating on behalf of an authorized user, and these agents are free to do anything the user is allowed to do, such as follow dangerous links. Google’s Web Accelerator is one such agent. It tries to make your surfing faster by (among other things) pre-fetching the resources that are linked to on the pages you visit. And what happens if you, an authorized user, visit a page containing dangerous links? That’s right, Web Accelerator will fetch the “resources” those links point to – and delete a bunch of your stuff.
I hope by this point that I have argued convincingly that using links for unsafe actions is a bad idea. Even if you feel justified in ignoring the applicable parts of the HTTP RFCs, it’s a bad idea. Even if you tack on Javascript confirmations and hide your links in authorization-protected zones of your site, it’s a bad idea. It is, all around, a bad idea. Don’t do it.
So what alternatives are there? Read on for one possibility, button_to.
Read more...
Posted in ruby, web development, rails
Tags get, gwa, link_to, post, rails, safe, unsafe
8 comments
no trackbacks
