1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/lib/action_controller/base/request_forgery_protection.rb

124 lines
6 KiB
Ruby
Raw Normal View History

module ActionController #:nodoc:
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
end
module RequestForgeryProtection
extend ActiveSupport::DependencyModule
# TODO : Remove the defined? check when new base is the main base
if defined?(ActionController::Http)
depends_on AbstractController::Helpers, Session
end
included do
if defined?(ActionController::Http)
# Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
# sets it to <tt>:authenticity_token</tt> by default.
cattr_accessor :request_forgery_protection_token
# Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
class_inheritable_accessor :allow_forgery_protection
self.allow_forgery_protection = true
end
helper_method :form_authenticity_token
helper_method :protect_against_forgery?
end
# Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current web application, not a
# forged link from another site, is done by embedding a token based on a random string stored in the session (which an attacker wouldn't know) in all
# forms and Ajax requests generated by Rails and then verifying the authenticity of that token in the controller. Only
# HTML/JavaScript requests are checked, so this will not protect your XML API (presumably you'll have a different authentication
2008-07-16 08:00:36 -04:00
# scheme there anyway). Also, GET requests are not protected as these should be idempotent anyway.
#
# This is turned on with the <tt>protect_from_forgery</tt> method, which will check the token and raise an
# ActionController::InvalidAuthenticityToken if it doesn't match what was expected. You can customize the error message in
# production by editing public/422.html. A call to this method in ApplicationController is generated by default in post-Rails 2.0
# applications.
#
# The token parameter is named <tt>authenticity_token</tt> by default. If you are generating an HTML form manually (without the
# use of Rails' <tt>form_for</tt>, <tt>form_tag</tt> or other helpers), you have to include a hidden field named like that and
# set its value to what is returned by <tt>form_authenticity_token</tt>. Same applies to manually constructed Ajax requests. To
# make the token available through a global variable to scripts on a certain page, you could add something like this to a view:
#
# <%= javascript_tag "window._token = '#{form_authenticity_token}'" %>
#
# Request forgery protection is disabled by default in test environment. If you are upgrading from Rails 1.x, add this to
# config/environments/test.rb:
#
# # Disable request forgery protection in test environment
# config.action_controller.allow_forgery_protection = false
#
# == Learn more about CSRF (Cross-Site Request Forgery) attacks
#
# Here are some resources:
# * http://isc.sans.org/diary.html?storyid=1750
# * http://en.wikipedia.org/wiki/Cross-site_request_forgery
#
# Keep in mind, this is NOT a silver-bullet, plug 'n' play, warm security blanket for your rails application.
# There are a few guidelines you should follow:
#
# * Keep your GET requests safe and idempotent. More reading material:
# * http://www.xml.com/pub/a/2002/04/24/deviant.html
# * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
# * Make sure the session cookies that Rails creates are non-persistent. Check in Firefox and look for "Expires: at end of session"
#
module ClassMethods
# Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.
#
# Example:
#
# class FooController < ApplicationController
# protect_from_forgery :except => :index
#
# # you can disable csrf protection on controller-by-controller basis:
# skip_before_filter :verify_authenticity_token
# end
#
# Valid Options:
#
Merge docrails: commit e6afd8b2736364322b673bbdcca3e9b38b6d3da0 Author: Xavier Noria <fxn@hashref.com> Date: Thu May 8 23:49:36 2008 +0200 Overall documentation improvement and markup corrections. Zillion changes. commit 2fead68b3192332eee27945ed95a94a64ca73f70 Author: Austin Putman <austin@emmanuel.local> Date: Wed May 7 19:35:46 2008 -0700 Documented class methods on ActionController::Routing. These are dangerous, and mostly used for testing. commit f5b84182dbc39bea79c8ee319c688d00fa99f9d1 Author: Teflon Ted <github@rudiment.net> Date: Wed May 7 16:08:49 2008 -0400 Added explanation about errant inflections not being patched in the future in order to avoid breaking legacy applications. commit 370f4f51722cec49ace17093d29e9ce9e8f15cfb Author: Sunny Ripert <negatif@gmail.com> Date: Wed May 7 14:00:59 2008 +0200 Applied list conventions in AR::Base commit 5bd18429f09d44e75191bec42a6db04bd33f3030 Author: Sunny Ripert <negatif@gmail.com> Date: Wed May 7 13:53:35 2008 +0200 Renamed Options list to Attributes list whenever they weren't option hashes in AR::Base commit d912bd5672316454457ae83f6e9dda5197beeb6f Author: Yaroslav Markin <yaroslav@markin.net> Date: Wed May 7 13:50:28 2008 +0400 Add a filter_parameter_logging usage hint to generated ApplicationController. This may help to remind the developer to filter sensitive information from application logs. Closes #11578 commit b243de0db3c2605121e055079854af5090d06374 Author: Jack Danger Canty <git@6brand.com> Date: Tue May 6 23:39:47 2008 -0700 doc: disambiguating an example ActiveRecord class commit f81d771f0657ae8375b84a77a059812cce5d6fd9 Author: Jack Danger Canty <git@6brand.com> Date: Tue May 6 23:35:05 2008 -0700 doc: ActiveRecord::Reflection::AssociationReflection#through_reflection Added documentation demonstrating the use of #through_reflection for finding intervening reflection objects for HasManyThrough and HasOneThrough. commit ae6b46f00b5b8b2939c6b37ce3329c83de7e71db Author: Cheah Chu Yeow <chuyeow@gmail.com> Date: Wed May 7 13:47:41 2008 +0800 Document AttributeAssignmentError and MultiparameterAssignmentErrors. commit 8f463550b597db2156b67733f31aed13487fbc3a Author: John Barnette <jbarnette@gmail.com> Date: Tue May 6 22:46:44 2008 -0700 Killing/fixing a bunch of outdated language in the AR README. commit aca44bcd92ef783abdf484b58abdde6786db0f89 Author: Cheah Chu Yeow <chuyeow@gmail.com> Date: Wed May 7 13:34:52 2008 +0800 Make a note about ActiveResource::Timeouterror being raised when ARes calls timeout. commit 284a930a93fbee16e25d06392779dbf2f03e9e12 Author: Jonathan Dance <jd@wuputah.com> Date: Tue May 6 14:58:26 2008 -0400 improvements to the page caching docs commit 9482da621390c874da7c921c8bd6230caae7035a Author: Sunny Ripert <negatif@gmail.com> Date: Mon May 5 18:13:40 2008 +0200 validates_numericality_of() "integer" option really is "only_integer" commit e9afd6790a8f530528f6597a7f59bb283be754f6 Author: Sunny Ripert <negatif@gmail.com> Date: Mon May 5 12:11:59 2008 +0200 Harmonized hash notation in AR::Base commit 67ebf14a91ffd970b582be4ff2991d691a9cf3e1 Author: Sunny Ripert <negatif@gmail.com> Date: Mon May 5 12:06:19 2008 +0200 Turned options into rdoc-lists in AR::Base commit 0ec7c0a41d889d4e5382b9dff72f1aaba89bf297 Author: Marshall Huss <mwhuss@Macbook.local> Date: Sun May 4 23:21:33 2008 -0400 Added information of how to set element_name in the case the user has a name confliction with an existing model Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
2008-05-09 05:38:02 -04:00
# * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call. Set which actions are verified.
def protect_from_forgery(options = {})
self.request_forgery_protection_token ||= :authenticity_token
before_filter :verify_authenticity_token, :only => options.delete(:only), :except => options.delete(:except)
if options[:secret] || options[:digest]
ActiveSupport::Deprecation.warn("protect_from_forgery only takes :only and :except options now. :digest and :secret have no effect", caller)
end
end
end
protected
# The actual before_filter that is used. Modify this to change how you handle unverified requests.
def verify_authenticity_token
verified_request? || raise(ActionController::InvalidAuthenticityToken)
end
# Returns true or false if a request is verified. Checks:
#
# * is the format restricted? By default, only HTML requests are checked.
# * is it a GET request? Gets should be safe and idempotent
# * Does the form_authenticity_token match the given token value from the params?
def verified_request?
!protect_against_forgery? ||
request.method == :get ||
request.xhr? ||
!verifiable_request_format? ||
form_authenticity_token == params[request_forgery_protection_token]
end
def verifiable_request_format?
!request.content_type.nil? && request.content_type.verify_request?
end
# Sets the token value for the current session. Pass a <tt>:secret</tt> option
# in +protect_from_forgery+ to add a custom salt to the hash.
def form_authenticity_token
session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32)
end
def protect_against_forgery?
allow_forgery_protection && request_forgery_protection_token
end
end
end