Class: Rack::Csrf

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/csrf.rb

Defined Under Namespace

Classes: InvalidCsrfToken, SessionUnavailable

Constant Summary collapse

@@field =
'_csrf'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, opts = {}) ⇒ Csrf



15
16
17
18
19
20
21
# File 'lib/rack/csrf.rb', line 15

def initialize(app, opts = {})
  @app = app
  @raisable = opts[:raise] || false
  @skippable = opts[:skip] || []
  @skippable.map {|s| s.downcase!}
  @@field = opts[:field] if opts[:field]
end

Class Method Details

.csrf_fieldObject



40
41
42
# File 'lib/rack/csrf.rb', line 40

def self.csrf_field
  @@field
end

.csrf_tag(env) ⇒ Object



48
49
50
# File 'lib/rack/csrf.rb', line 48

def self.csrf_tag(env)
  %Q(<input type="hidden" name="#{csrf_field}" value="#{csrf_token(env)}" />)
end

.csrf_token(env) ⇒ Object



44
45
46
# File 'lib/rack/csrf.rb', line 44

def self.csrf_token(env)
  env['rack.session']['csrf.token'] ||= SecureRandom.base64(32)
end

Instance Method Details

#call(env) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rack/csrf.rb', line 23

def call(env)
  unless env['rack.session']
    raise SessionUnavailable.new('Rack::Csrf depends on session middleware')
  end
  self.class.csrf_token(env)
  req = Rack::Request.new(env)
  untouchable = !%w(POST PUT DELETE).include?(req.request_method) ||
    req.POST[self.class.csrf_field] == env['rack.session']['csrf.token'] ||
    skip_checking(req)
  if untouchable
    @app.call(env)
  else
    raise InvalidCsrfToken if @raisable
    [417, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]
  end
end