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'
@@key =
'csrf.token'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Csrf.



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rack/csrf.rb', line 16

def initialize(app, opts = {})
  @app = app

  @raisable = opts[:raise] || false
  @to_be_skipped = (opts[:skip] || []).map {|r| /\A#{r}\Z/i}
  @to_be_checked = (opts[:check_only] || []).map {|r| /\A#{r}\Z/i}
  @@field = opts[:field] if opts[:field]
  @@key = opts[:key] if opts[:key]

  standard_http_methods = %w(POST PUT DELETE PATCH)
  check_also = opts[:check_also] || []
  @http_methods = (standard_http_methods + check_also).flatten.uniq
end

Class Method Details

.fieldObject Also known as: csrf_field



51
52
53
# File 'lib/rack/csrf.rb', line 51

def self.field
  @@field
end

.keyObject Also known as: csrf_key



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

def self.key
  @@key
end

.tag(env) ⇒ Object Also known as: csrf_tag



59
60
61
# File 'lib/rack/csrf.rb', line 59

def self.tag(env)
  %Q(<input type="hidden" name="#{field}" value="#{token(env)}" />)
end

.token(env) ⇒ Object Also known as: csrf_token



55
56
57
# File 'lib/rack/csrf.rb', line 55

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

Instance Method Details

#call(env) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rack/csrf.rb', line 30

def call(env)
  unless env['rack.session']
    raise SessionUnavailable.new('Rack::Csrf depends on session middleware')
  end
  self.class.token(env)
  req = Rack::Request.new(env)
  untouchable = skip_checking(req) ||
    !@http_methods.include?(req.request_method) ||
    req.params[self.class.field] == env['rack.session'][self.class.key]
  if untouchable
    @app.call(env)
  else
    raise InvalidCsrfToken if @raisable
    [403, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]
  end
end