Whitelist Your Routes, "match" is Evil
homakov.blogspot.com
homakov.blogspot.com
Instead of writing:
do_thing()
He's suggesting you write: if(preconditions_are_met())
do_thing()
?Sounds good to me.
I propose ALWAYS specify HTTP verb for action - because you always know which way controller#action should be used. If you dont - you are doing it wrong.
The same CSRF rules apply to GET and POST requests. If you're using proper CSRF protection it doesn't really matter if you do a GET or POST. The only real difference is that GET requests will be visible to every piece of hardware between the user and your server whether you're using SSL or not and will most likely be logged. Also you can upload files via POST.
While it's easier to make users send harmful GET requests by putting the URL in an image you can simply use JS to POST a hidden form. Thinking POST is inherently more secure is a false assumption. Both are equally vulnerable to CSRF.
It's entirely possible I mis-understand the whole thing and please correct me if I am wrong (and explain why).
>If you're a web dev making these mistakes then you need to take the time to learn about basic web security.
Honestly, I didn't say it loudly but I meant it. Not understanding GET/POST makes person low skilled dev.
Now that's interesting, I wasn't aware of that. It makes sense due to the Rails convention being GET is only for fetching data. So this does make GET more insecure than POST for Rails.
Currently I'm feeling very superior about how my framework is more secure than yours, but I'd love to see you shoot down that silly notion.
if request.method not in ('POST', 'PUT', 'DELETE', 'PATCH'):
...
at the top of every method (or use a decorator), but it'd definitely be nice if this were part of the url dispatcher.Finding rails issues and then saying "they kinda sorta apply to Django" isn't as interesting as finding real Django issues.
To yummyfajitas - your message is 50% trolling. Will you allow me to troll a little bit? I used django and scrapy few years ago and despite the fact it was better than PHP I would not even dare to compare it with Rails. Rails is that superior I don't even have words to explain it :D Conclusion: I'm not interested in Django and its bug because I love rails and wanna make it more secure anyways. Sorry, but Django is way less convinient to use. Security is another story though.
Also, if you ever manage to put into words why you prefer Rails, I'd love to read it. Django and rails seem pretty similar to me, but I didn't put much effort into learning rails. But maybe I'm just experiencing the blub paradox.
It was a problem with the older function based views, and there was a lot of boilerplate to ensure the correct HTTP verb was being used.
from django.views.generic.base import View
from django.http import HttpResponse
class MyView(View):
def get(self, request):
return HttpResponse("Get request")
def post(self, request):
return HttpResponse("Post Request")
The functionality to make this "just work" (dispatch based on method) is built into django.views.generic.base.View.dispatch.The match statement is good for the occasional odd cases, but it has an :via option that can be used to restrict which HTTP actions it is allowed to match.
Edit: corrected below...thanks!
and there are almost no odd cases in fact. I would propose special route named "not_found" or "default" like route to be called if no routes found. Nice idea IMO, what do you think?
I had to use match when moving from Rails 2 to Rails 3 and parts of the route did not match the controller at all. But I think it was mostly because the upgrade plugin recommended it.
get '/foo' => 'foos#index', as: :foo
post '/foo' => 'foos#new', as: :new_foo
get '/foo/:id' => 'foos#show', as: :show_foo
put '/foo/:id' => 'foos#edit', as: :edit_foo
delete '/foo/:id' => 'foos#destroy', as: :destroy_foo
or scope them if you'd like: scope controller: "foo", constraints: { id: /0-9]+/ } do
get '/foo' => :index, as: :foo
post '/foo' => :new, as: :new_foo
put ...
delete ...
endAnd, again! PLEASE use method "data" instead of match :via => method. It's much better and looks clean.
Rails 2.3 had "verify :method => :post" which was supposed to be used in controllers. This is nothing new.
map.connect "/foo", :controller => "foos", :action => "index", :conditions => { :method => :get }
Which is the "correct" way to do verb-constrained non-resource routes. Not ever routing the wrong verb is even better than checking it in the controller.Anyways rails 2.3 had no csrf protection
Ok, then you're a bad coder. All Rails applications I've ever worked on had those checks and the documentation for Rails made it pretty clear that verify :method should be used for non-GET requests.
Anyways rails 2.3 had no csrf protection
You really need to check your facts. Rails has had protect_from_forgery since at least 2.2 and it was enabled by default in ApplicationController. Rails < 2.3.10 did not do the verification for AJAX requests, but this was changed in 2.3.11.
Added in 2007: https://github.com/rails/rails/commit/4e3ed5bc44f6cd20c9e353... and made the default shortly after.
Ops FIX: you should call bad coder not me but people whom code I had been reading years ago.
And anyways burke is right: >Supposed to be, but rarely was. Throw a bunch of new programmers at a framework, and insecure-by-default becomes insecure.
btw verify method: :post is nice to have but obviously uglier than current routes.rb DSL.