Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
820 views
in Technique[技术] by (71.8m points)

ruby - How does Rails CSRF protection work?

Rails raises an InvalidAuthenticityToken when the CSRF token doesn't match. But, from reading the source, I can't figure out how this actually happens. I start by acking the tree for that class:

$ ack --ignore-dir=test InvalidAuthenticityToken

actionpack/lib/action_controller/metal/request_forgery_protection.rb
4:  class InvalidAuthenticityToken < ActionControllerError #:nodoc:
17:  # which will check the token and raise an ActionController::InvalidAuthenticityToken

actionpack/lib/action_dispatch/middleware/show_exceptions.rb
22:      'ActionController::InvalidAuthenticityToken' => :unprocessable_entity

Only two hits, ignoring the comment. The first one is the class definition:

class InvalidAuthenticityToken < ActionControllerError #:nodoc:
end

The second one is translating the exception into an HTTP status code. CSRF protection gets enabled by calling protect_from_forgery in the controller, so let's look at that:

def protect_from_forgery(options = {})
  self.request_forgery_protection_token ||= :authenticity_token
  before_filter :verify_authenticity_token, options
end

It adds a filter:

def verify_authenticity_token
  verified_request? || handle_unverified_request
end

Which calls this when verification fails:

def handle_unverified_request
  reset_session
end

So how is InvalidAuthenticityToken actually raised?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The behavior was changed fairly recently but the documentation has yet to be updated. The new approach being used is to presume the session has been hijacked, and therefore to clear the session. Assuming your session contains the all-important authentication information for this request (like the fact you're logged in as alice) and your controller assures the user is authenticated for this action, your request will be redirected to a login page (or however you choose to handle a non logged-in user). However, for requests which are not authenticated, like a sign-up form, the request would go through using an empty session.

It seems this commit also goes on to close a CSRF vulnerability, but I didn't read into the details of that.

To obtain the old behavior, you would simply define this method:

def handle_unverified_request
  raise(ActionController::InvalidAuthenticityToken)
end

You can read more about CSRF and other Rails security issues at the Ruby on Rails Security Guide.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...