OSDN Git Service

pryを導入
[elecoma/elecoma.git] / lib / security_token.rb
1 # CSRF 対策
2
3 module ActionView::Helpers
4   module TagHelper
5     def tag_with_security_token(name, *args)
6       if name.to_sym == :form && @form_tag_add_security_token
7         tag_without_security_token(name, *args) + hidden_field_tag("session_token", session_token)
8       else
9         tag_without_security_token(name, *args)
10       end
11     end
12
13     alias_method_chain :tag, :security_token
14   end
15
16   module FormTagHelper
17     def form_tag_with_security_token(url_for_options = {}, options = {}, *parameters_for_url, &proc)
18       if (options[:method].nil? || /^post$/i =~ options[:method].to_s) && false != options.delete(:security_token)
19         begin
20           @form_tag_add_security_token = true
21           form_tag_without_security_token(url_for_options, options, *parameters_for_url, &proc)
22         ensure
23           @form_tag_add_security_token = nil
24         end
25       else
26         form_tag_without_security_token(url_for_options, options, *parameters_for_url, &proc)
27       end
28     end
29     
30     alias_method_chain :form_tag, :security_token
31     alias_method :start_form_tag, :form_tag
32   end
33 end
34
35 module ActionView::Helpers::UrlHelper
36   def method_javascript_function_with_session_token(method, url='', href=nil)
37     f = method_javascript_function_without_session_token(method, url='', href=nil)
38     if method.to_sym == :post
39       token_func = "var t = document.createElement('input'); t.type='hidden'; t.name='session_token'; t.value='#{session_token}'; "
40       f.sub!(/f.submit\(\)/, 'f.appendChild(t); \&') || raise("substitution failed")
41       token_func << f
42       token_func
43     else
44       f
45     end
46   end
47
48   alias_method_chain :method_javascript_function, :session_token
49
50   def button_to_with_session_token(*args)
51     button_to_without_session_token(*args).sub(/<\/form>$/, 
52                                                "#{hidden_field_tag('session_token', session_token)}</form>")
53   end
54   
55   alias_method_chain :button_to, :session_token
56 end
57
58 class ActionController::Base
59   def session_token
60     session[:session_token] ||= Digest::MD5.hexdigest("#{session.session_id}#{rand}")
61   end
62
63   def verify_session_token
64     if request.post? &&
65         !request.xhr? &&
66         !(::ActionController.const_defined?("TestRequest") && request.is_a?(::ActionController::TestRequest))
67       if session_token == params["session_token"]
68         return true
69       else
70         render :text => 'errors/forbidden', :status => 403, :layout => false
71         return false
72       end
73     end
74     true
75   end
76
77   helper_method :session_token
78 end