rack_csrf 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.md +12 -0
- data/README.rdoc +29 -6
- data/Rakefile +5 -3
- data/VERSION +1 -1
- data/examples/camping/Gemfile +2 -2
- data/examples/camping/app.rb +1 -1
- data/examples/cuba/Gemfile +3 -0
- data/examples/cuba/README.rdoc +11 -0
- data/examples/cuba/app.rb +17 -0
- data/examples/cuba/config-with-raise.ru +11 -0
- data/examples/cuba/config.ru +10 -0
- data/examples/cuba/views/form.erb +8 -0
- data/examples/cuba/views/form_not_working.erb +7 -0
- data/examples/cuba/views/response.erb +5 -0
- data/examples/innate/Gemfile +1 -1
- data/examples/innate/app.rb +1 -1
- data/examples/innate/view/index.erb +1 -1
- data/examples/rack/Gemfile +1 -1
- data/examples/rack/app.rb +2 -2
- data/examples/sinatra/Gemfile +1 -1
- data/examples/sinatra/app.rb +1 -1
- data/examples/sinatra/views/form.erb +1 -1
- data/features/check_only_some_specific_requests.feature +28 -0
- data/features/custom_http_methods.feature +62 -0
- data/features/empty_responses.feature +8 -6
- data/features/inspecting_also_get_requests.feature +20 -0
- data/features/raising_exception.feature +3 -4
- data/features/setup.feature +16 -0
- data/features/step_definitions/request_steps.rb +8 -13
- data/features/step_definitions/setup_steps.rb +24 -0
- data/features/variation_on_field_name.feature +8 -4
- data/features/variation_on_key_name.feature +8 -4
- data/lib/rack/csrf.rb +26 -17
- data/rack_csrf.gemspec +24 -10
- data/spec/csrf_spec.rb +110 -33
- metadata +34 -7
data/Changelog.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
# v2.3.0 (2011-10-23)
|
2
|
+
|
3
|
+
* Updated examples' Gemfiles.
|
4
|
+
* Moved to use the RDoc gem.
|
5
|
+
* new option :check_only (courtesy of [ghermeto](https://github.com/ghermeto))
|
6
|
+
* Cuba example.
|
7
|
+
* Changed request checking to look at GET+POST data.
|
8
|
+
* Added support for custom HTTP methods.
|
9
|
+
* Promoted public methods' shorter aliases to main API.
|
10
|
+
|
11
|
+
|
12
|
+
|
1
13
|
# v2.2.0 (2011-04-12)
|
2
14
|
|
3
15
|
* Simplified specs and some Cucumber's steps.
|
data/README.rdoc
CHANGED
@@ -34,6 +34,20 @@ The following options allow you to tweak Rack::Csrf.
|
|
34
34
|
|
35
35
|
Default value: false.
|
36
36
|
|
37
|
+
[<tt>:check_only</tt>]
|
38
|
+
By default, Rack::Csrf checks every POST, PUT, DELETE and PATCH request;
|
39
|
+
passing an array of HTTP method/URL (regular expressions allowed) to this
|
40
|
+
option you can change this behavior to *only* check the items on this list.
|
41
|
+
|
42
|
+
use Rack::Csrf, :check_only => ['POST:/checking', 'PUT:/me_too',
|
43
|
+
'DELETE:/cars/.*\.xml', 'PATCH:/this/.*/too']
|
44
|
+
|
45
|
+
Please, note that the regular expressions are not escaped and it is your
|
46
|
+
duty to write them correctly. Empty PATH_INFO (see Rack's spec for details)
|
47
|
+
is treated as '/' for this check.
|
48
|
+
|
49
|
+
Default value: empty.
|
50
|
+
|
37
51
|
[<tt>:skip</tt>]
|
38
52
|
By default, Rack::Csrf checks every POST, PUT, DELETE and PATCH request;
|
39
53
|
passing an array of HTTP method/URL (regular expressions allowed) to this
|
@@ -64,6 +78,15 @@ The following options allow you to tweak Rack::Csrf.
|
|
64
78
|
|
65
79
|
Default value: csrf.token
|
66
80
|
|
81
|
+
[<tt>:check_also</tt>]
|
82
|
+
By passing an array of uppercase strings to this option you can add them to
|
83
|
+
the list of HTTP methods which "mark" requests that must be searched for the
|
84
|
+
anti-forging token.
|
85
|
+
|
86
|
+
use Rack::Csrf, :check_also => %w(WHATEVER YOU WANT EVEN GET)
|
87
|
+
|
88
|
+
Default value: empty
|
89
|
+
|
67
90
|
The <tt>:browser_only</tt> option has been removed; you do not need to edit
|
68
91
|
any rackup file because Rack::Csrf simply ignores unknown options. Changes
|
69
92
|
introduced in Rack version 1.1.0 tightened the parsing of POST params, so
|
@@ -80,19 +103,19 @@ The ill devised <tt>:browser_only</tt> option could have been used to
|
|
80
103
|
The following class methods try to ease the insertion of the anti-forging
|
81
104
|
token.
|
82
105
|
|
83
|
-
[<tt>Rack::Csrf.
|
106
|
+
[<tt>Rack::Csrf.key</tt> (also <tt>Rack::Csrf.csrf_key</tt>)]
|
84
107
|
Returns the name of the key used to store/retrieve the token from the Rack
|
85
108
|
session.
|
86
109
|
|
87
|
-
[<tt>Rack::Csrf.
|
110
|
+
[<tt>Rack::Csrf.field</tt> (also <tt>Rack::Csrf.csrf_field</tt>)]
|
88
111
|
Returns the name of the field that must be present in the request.
|
89
112
|
|
90
|
-
[<tt>Rack::Csrf.
|
113
|
+
[<tt>Rack::Csrf.token(env)</tt> (also <tt>Rack::Csrf.csrf_token(env)</tt>)]
|
91
114
|
Given the request's environment, it generates a random token, stuffs it in
|
92
115
|
the session and returns it to the caller or simply retrieves the already
|
93
116
|
stored one.
|
94
117
|
|
95
|
-
[<tt>Rack::Csrf.
|
118
|
+
[<tt>Rack::Csrf.tag(env)</tt> (also <tt>Rack::Csrf.csrf_tag(env)</tt>)]
|
96
119
|
Given the request's environment, it generates a small HTML fragment to
|
97
120
|
insert the token in a standard form like an hidden input field with the
|
98
121
|
right value already entered for you.
|
@@ -107,7 +130,7 @@ framework; see the various README files for other details.
|
|
107
130
|
|
108
131
|
If you want to help:
|
109
132
|
|
110
|
-
* fork the project[
|
133
|
+
* fork the project[https://github.com/baldowl/rack_csrf] on GitHub;
|
111
134
|
* work in a topic branch;
|
112
135
|
* add features/specs for your additions or bug fixes;
|
113
136
|
* write your additions/bug fixes;
|
@@ -115,7 +138,7 @@ If you want to help:
|
|
115
138
|
* send me a pull request for the topic branch.
|
116
139
|
|
117
140
|
If you have any issue, please post them on the {project's issue
|
118
|
-
list}[
|
141
|
+
list}[https://github.com/baldowl/rack_csrf] on GitHub.
|
119
142
|
|
120
143
|
== Warning! Warning! Warning!
|
121
144
|
|
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rake/clean'
|
2
2
|
require 'cucumber/rake/task'
|
3
3
|
require 'rspec/core/rake_task'
|
4
|
-
require '
|
4
|
+
require 'rdoc/task'
|
5
5
|
require 'jeweler'
|
6
6
|
|
7
7
|
Cucumber::Rake::Task.new :features
|
@@ -14,9 +14,10 @@ task :default => :spec
|
|
14
14
|
|
15
15
|
version = File.exists?('VERSION') ? File.read('VERSION').strip : ''
|
16
16
|
|
17
|
-
|
17
|
+
RDoc::Task.new :doc do |rdoc|
|
18
18
|
rdoc.rdoc_dir = 'doc'
|
19
19
|
rdoc.title = "Rack::Csrf #{version}"
|
20
|
+
rdoc.main = 'README.rdoc'
|
20
21
|
rdoc.rdoc_files.include('README.rdoc', 'LICENSE.rdoc')
|
21
22
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
23
|
end
|
@@ -28,12 +29,13 @@ Jeweler::Tasks.new do |gem|
|
|
28
29
|
gem.license = 'MIT'
|
29
30
|
gem.authors = 'Emanuele Vicentini'
|
30
31
|
gem.email = 'emanuele.vicentini@gmail.com'
|
31
|
-
gem.homepage = '
|
32
|
+
gem.homepage = 'https://github.com/baldowl/rack_csrf'
|
32
33
|
gem.rubyforge_project = 'rackcsrf'
|
33
34
|
gem.add_dependency 'rack', '>= 0.9'
|
34
35
|
gem.add_development_dependency 'cucumber', '>= 0.1.13'
|
35
36
|
gem.add_development_dependency 'rack-test'
|
36
37
|
gem.add_development_dependency 'rspec', '>= 2.0.0'
|
38
|
+
gem.add_development_dependency 'rdoc', '>= 2.4.2'
|
37
39
|
gem.rdoc_options << '--line-numbers' << '--inline-source' << '--title' <<
|
38
40
|
"Rack::Csrf #{version}" << '--main' << 'README.rdoc'
|
39
41
|
gem.test_files.clear
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.3.0
|
data/examples/camping/Gemfile
CHANGED
data/examples/camping/app.rb
CHANGED
@@ -37,7 +37,7 @@ module LittleApp
|
|
37
37
|
form :action => URL(Response), :method => :post do
|
38
38
|
h1 'Spit your utterance!'
|
39
39
|
input :name => :utterance, :type => :text
|
40
|
-
text Rack::Csrf.
|
40
|
+
text Rack::Csrf.tag(@env)
|
41
41
|
p {
|
42
42
|
input :type => :submit, :value => :Send!
|
43
43
|
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
= How to use Rack::Csrf with Cuba
|
2
|
+
|
3
|
+
This is a mini Cuba application with two slightly different rackup files.
|
4
|
+
Beside Rack you only need Cuba to try them, so, assuming you have Bundler
|
5
|
+
installed, run:
|
6
|
+
|
7
|
+
$ bundle install
|
8
|
+
$ bundle exec rackup -p 3000 config.ru
|
9
|
+
$ bundle exec rackup -p 3000 config-with-raise.ru
|
10
|
+
|
11
|
+
Tested with Cuba versions listed in the Gemfile.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Cuba.define do
|
2
|
+
on get do
|
3
|
+
on '' do
|
4
|
+
res.write render('views/form.erb')
|
5
|
+
end
|
6
|
+
|
7
|
+
on 'notworking' do
|
8
|
+
res.write render('views/form_not_working.erb')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
on post do
|
13
|
+
on 'response', param(:utterance), param(Rack::Csrf.field) do |utterance, csrf|
|
14
|
+
res.write render('views/response.erb', :utterance => utterance, :csrf => csrf)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/examples/innate/Gemfile
CHANGED
data/examples/innate/app.rb
CHANGED
data/examples/rack/Gemfile
CHANGED
data/examples/rack/app.rb
CHANGED
@@ -3,7 +3,7 @@ class LittleApp
|
|
3
3
|
<form action="/response" method="post">
|
4
4
|
<h1>Spit your utterance!</h1>
|
5
5
|
<input type="text" name="utterance">
|
6
|
-
<%= Rack::Csrf.
|
6
|
+
<%= Rack::Csrf.tag(env) %>
|
7
7
|
<p><input type="submit" value="Send!"></p>
|
8
8
|
</form>
|
9
9
|
|
@@ -38,7 +38,7 @@ class LittleApp
|
|
38
38
|
end
|
39
39
|
elsif req.post?
|
40
40
|
utterance = req['utterance']
|
41
|
-
csrf = req[Rack::Csrf.
|
41
|
+
csrf = req[Rack::Csrf.field]
|
42
42
|
Rack::Response.new(@response.result(binding)).finish
|
43
43
|
end
|
44
44
|
end
|
data/examples/sinatra/Gemfile
CHANGED
data/examples/sinatra/app.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: Check only some specific requests
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a rack with the anti-CSRF middleware and the :check_only option
|
5
|
+
| pair |
|
6
|
+
| POST:/check/this |
|
7
|
+
|
8
|
+
Scenario: Blocking that specific request
|
9
|
+
When it receives a POST request for /check/this without the CSRF token
|
10
|
+
Then it responds with 403
|
11
|
+
|
12
|
+
Scenario Outline: Not blocking other requests
|
13
|
+
When it receives a <method> request for <path> without the CSRF token
|
14
|
+
Then it lets it pass untouched
|
15
|
+
|
16
|
+
Examples:
|
17
|
+
| method | path |
|
18
|
+
| GET | /check/this |
|
19
|
+
| PUT | /check/this |
|
20
|
+
| PATCH | /check/this |
|
21
|
+
| DELETE | /check/this |
|
22
|
+
| CUSTOM | /check/this |
|
23
|
+
| GET | /another/one |
|
24
|
+
| POST | /another/one |
|
25
|
+
| PUT | /another/one |
|
26
|
+
| PATCH | /another/one |
|
27
|
+
| DELETE | /another/one |
|
28
|
+
| CUSTOM | /another/one |
|
@@ -0,0 +1,62 @@
|
|
1
|
+
Feature: Handling custom HTTP methods
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a rack with the anti-CSRF middleware and the :check_also option
|
5
|
+
| method |
|
6
|
+
| ME |
|
7
|
+
| YOU |
|
8
|
+
|
9
|
+
Scenario Outline: Blocking "standard" requests without the token
|
10
|
+
When it receives a <method> request without the CSRF token
|
11
|
+
Then it responds with 403
|
12
|
+
And the response body is empty
|
13
|
+
|
14
|
+
Examples:
|
15
|
+
| method |
|
16
|
+
| POST |
|
17
|
+
| PUT |
|
18
|
+
| DELETE |
|
19
|
+
| PATCH |
|
20
|
+
|
21
|
+
Scenario Outline: Blocking "standard" requests with the wrong token
|
22
|
+
When it receives a <method> request with the wrong CSRF token
|
23
|
+
Then it responds with 403
|
24
|
+
And the response body is empty
|
25
|
+
|
26
|
+
Examples:
|
27
|
+
| method |
|
28
|
+
| POST |
|
29
|
+
| PUT |
|
30
|
+
| DELETE |
|
31
|
+
| PATCH |
|
32
|
+
|
33
|
+
Scenario Outline: Blocking requests without the token
|
34
|
+
When it receives a <method> request without the CSRF token
|
35
|
+
Then it responds with 403
|
36
|
+
And the response body is empty
|
37
|
+
|
38
|
+
Examples:
|
39
|
+
| method |
|
40
|
+
| ME |
|
41
|
+
| YOU |
|
42
|
+
|
43
|
+
Scenario Outline: Blocking requests with the wrong token
|
44
|
+
When it receives a <method> request with the wrong CSRF token
|
45
|
+
Then it responds with 403
|
46
|
+
And the response body is empty
|
47
|
+
|
48
|
+
Examples:
|
49
|
+
| method |
|
50
|
+
| ME |
|
51
|
+
| YOU |
|
52
|
+
|
53
|
+
Scenario Outline: Letting pass "unknown" and safe requests without the token
|
54
|
+
When it receives a <method> request without the CSRF token
|
55
|
+
Then it lets it pass untouched
|
56
|
+
|
57
|
+
Examples:
|
58
|
+
| method |
|
59
|
+
| HIM |
|
60
|
+
| HER |
|
61
|
+
| GET |
|
62
|
+
| OPTIONS |
|
@@ -1,17 +1,21 @@
|
|
1
1
|
Feature: Handling of the HTTP requests returning an empty response
|
2
2
|
|
3
|
-
|
3
|
+
Background:
|
4
4
|
Given a rack with the anti-CSRF middleware
|
5
|
-
|
5
|
+
|
6
|
+
Scenario: GET request with the right CSRF token
|
7
|
+
When it receives a GET request with the right CSRF token
|
8
|
+
Then it lets it pass untouched
|
9
|
+
|
10
|
+
Scenario: GET request with the wrong CSRF token
|
11
|
+
When it receives a GET request with the wrong CSRF token
|
6
12
|
Then it lets it pass untouched
|
7
13
|
|
8
14
|
Scenario: GET request without CSRF token
|
9
|
-
Given a rack with the anti-CSRF middleware
|
10
15
|
When it receives a GET request without the CSRF token
|
11
16
|
Then it lets it pass untouched
|
12
17
|
|
13
18
|
Scenario Outline: Handling request without CSRF token
|
14
|
-
Given a rack with the anti-CSRF middleware
|
15
19
|
When it receives a <method> request without the CSRF token
|
16
20
|
Then it responds with 403
|
17
21
|
And the response body is empty
|
@@ -24,7 +28,6 @@ Feature: Handling of the HTTP requests returning an empty response
|
|
24
28
|
| PATCH |
|
25
29
|
|
26
30
|
Scenario Outline: Handling request with the right CSRF token
|
27
|
-
Given a rack with the anti-CSRF middleware
|
28
31
|
When it receives a <method> request with the right CSRF token
|
29
32
|
Then it lets it pass untouched
|
30
33
|
|
@@ -36,7 +39,6 @@ Feature: Handling of the HTTP requests returning an empty response
|
|
36
39
|
| PATCH |
|
37
40
|
|
38
41
|
Scenario Outline: Handling request with the wrong CSRF token
|
39
|
-
Given a rack with the anti-CSRF middleware
|
40
42
|
When it receives a <method> request with the wrong CSRF token
|
41
43
|
Then it responds with 403
|
42
44
|
And the response body is empty
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Inspecting also GET requests
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a rack with the anti-CSRF middleware and the :check_also option
|
5
|
+
| method |
|
6
|
+
| GET |
|
7
|
+
|
8
|
+
Scenario: GET request with the right CSRF token
|
9
|
+
When it receives a GET request with the right CSRF token
|
10
|
+
Then it lets it pass untouched
|
11
|
+
|
12
|
+
Scenario: GET request with the wrong CSRF token
|
13
|
+
When it receives a GET request with the wrong CSRF token
|
14
|
+
Then it responds with 403
|
15
|
+
And the response body is empty
|
16
|
+
|
17
|
+
Scenario: GET request without the CSRF token
|
18
|
+
When it receives a GET request without the CSRF token
|
19
|
+
Then it responds with 403
|
20
|
+
And the response body is empty
|
@@ -1,12 +1,13 @@
|
|
1
1
|
Feature: Handling of the HTTP requests raising an exception
|
2
2
|
|
3
|
-
|
3
|
+
Background:
|
4
4
|
Given a rack with the anti-CSRF middleware and the :raise option
|
5
|
+
|
6
|
+
Scenario: GET request without CSRF token
|
5
7
|
When it receives a GET request without the CSRF token
|
6
8
|
Then it lets it pass untouched
|
7
9
|
|
8
10
|
Scenario Outline: Handling request without CSRF token
|
9
|
-
Given a rack with the anti-CSRF middleware and the :raise option
|
10
11
|
When it receives a <method> request without the CSRF token
|
11
12
|
Then there is no response
|
12
13
|
And an exception is climbing up the stack
|
@@ -19,7 +20,6 @@ Feature: Handling of the HTTP requests raising an exception
|
|
19
20
|
| PATCH |
|
20
21
|
|
21
22
|
Scenario Outline: Handling request with the right CSRF token
|
22
|
-
Given a rack with the anti-CSRF middleware and the :raise option
|
23
23
|
When it receives a <method> request with the right CSRF token
|
24
24
|
Then it lets it pass untouched
|
25
25
|
|
@@ -31,7 +31,6 @@ Feature: Handling of the HTTP requests raising an exception
|
|
31
31
|
| PATCH |
|
32
32
|
|
33
33
|
Scenario Outline: Handling request with the wrong CSRF token
|
34
|
-
Given a rack with the anti-CSRF middleware and the :raise option
|
35
34
|
When it receives a <method> request with the wrong CSRF token
|
36
35
|
Then there is no response
|
37
36
|
And an exception is climbing up the stack
|
data/features/setup.feature
CHANGED
@@ -32,3 +32,19 @@ Feature: Setup of the middleware
|
|
32
32
|
Given a rack with the session middleware
|
33
33
|
When I insert the anti-CSRF middleware with the :key option
|
34
34
|
Then I get a fully functional rack
|
35
|
+
|
36
|
+
Scenario: Setup with the :check_also option
|
37
|
+
Given a rack with the session middleware
|
38
|
+
When I insert the anti-CSRF middleware with the :check_also option
|
39
|
+
| method |
|
40
|
+
| ME |
|
41
|
+
| YOU |
|
42
|
+
Then I get a fully functional rack
|
43
|
+
|
44
|
+
Scenario: Setup with the :check_only option
|
45
|
+
Given a rack with the session middleware
|
46
|
+
When I insert the anti-CSRF middleware with the :check_only option
|
47
|
+
| route |
|
48
|
+
| POST:/check/me |
|
49
|
+
| PUT:/check/this/too |
|
50
|
+
Then I get a fully functional rack
|
@@ -1,12 +1,7 @@
|
|
1
|
-
When /^it receives a GET request (with|without) the CSRF token$/ do |prep|
|
2
|
-
params = prep == 'with' ? {Rack::Csrf.csrf_field => 'whatever'} : {}
|
3
|
-
@browser.get '/', :params => params
|
4
|
-
end
|
5
|
-
|
6
1
|
# Yes, they're not as DRY as possible, but I think they're more readable than
|
7
2
|
# a single step definition with a few captures and more complex checkings.
|
8
3
|
|
9
|
-
When /^it receives a (
|
4
|
+
When /^it receives a (.*) request without the CSRF token$/ do |http_method|
|
10
5
|
begin
|
11
6
|
@browser.request '/', :method => http_method
|
12
7
|
rescue Exception => e
|
@@ -14,7 +9,7 @@ When /^it receives a (POST|PUT|DELETE|PATCH) request without the CSRF token$/ do
|
|
14
9
|
end
|
15
10
|
end
|
16
11
|
|
17
|
-
When /^it receives a (
|
12
|
+
When /^it receives a (.*) request for (.+) without the CSRF token$/ do |http_method, path|
|
18
13
|
begin
|
19
14
|
@browser.request path, :method => http_method
|
20
15
|
rescue Exception => e
|
@@ -22,22 +17,22 @@ When /^it receives a (POST|PUT|DELETE|PATCH) request for (.+) without the CSRF t
|
|
22
17
|
end
|
23
18
|
end
|
24
19
|
|
25
|
-
When /^it receives a (
|
20
|
+
When /^it receives a (.*) request with the right CSRF token$/ do |http_method|
|
26
21
|
@browser.request '/', :method => http_method,
|
27
|
-
'rack.session' => {Rack::Csrf.
|
28
|
-
:params => {Rack::Csrf.
|
22
|
+
'rack.session' => {Rack::Csrf.key => 'right_token'},
|
23
|
+
:params => {Rack::Csrf.field => 'right_token'}
|
29
24
|
end
|
30
25
|
|
31
|
-
When /^it receives a (
|
26
|
+
When /^it receives a (.*) request with the wrong CSRF token$/ do |http_method|
|
32
27
|
begin
|
33
28
|
@browser.request '/', :method => http_method,
|
34
|
-
:params => {Rack::Csrf.
|
29
|
+
:params => {Rack::Csrf.field => 'whatever'}
|
35
30
|
rescue Exception => e
|
36
31
|
@exception = e
|
37
32
|
end
|
38
33
|
end
|
39
34
|
|
40
|
-
When /^it receives a (
|
35
|
+
When /^it receives a (.*) request with neither PATH_INFO nor CSRF token$/ do |http_method|
|
41
36
|
begin
|
42
37
|
@browser.request '/doesntmatter', :method => http_method, 'PATH_INFO' => ''
|
43
38
|
rescue Exception => e
|
@@ -32,6 +32,16 @@ Given /^a rack with the anti\-CSRF middleware and the :key option$/ do
|
|
32
32
|
When 'I insert the anti-CSRF middleware with the :key option'
|
33
33
|
end
|
34
34
|
|
35
|
+
Given /^a rack with the anti\-CSRF middleware and the :check_also option$/ do |table|
|
36
|
+
Given 'a rack with the session middleware'
|
37
|
+
When 'I insert the anti-CSRF middleware with the :check_also option', table
|
38
|
+
end
|
39
|
+
|
40
|
+
Given /^a rack with the anti\-CSRF middleware and the :check_only option$/ do |table|
|
41
|
+
Given 'a rack with the session middleware'
|
42
|
+
When 'I insert the anti-CSRF middleware with the :check_only option', table
|
43
|
+
end
|
44
|
+
|
35
45
|
# Yes, they're not as DRY as possible, but I think they're more readable than
|
36
46
|
# a single step definition with a few captures and more complex checkings.
|
37
47
|
|
@@ -66,6 +76,20 @@ When /^I insert the anti\-CSRF middleware with the :key option$/ do
|
|
66
76
|
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
67
77
|
end
|
68
78
|
|
79
|
+
When /^I insert the anti\-CSRF middleware with the :check_also option$/ do |table|
|
80
|
+
check_also = table.hashes.collect {|t| t.values}.flatten
|
81
|
+
@rack_builder.use Rack::Csrf, :check_also => check_also
|
82
|
+
@app = toy_app
|
83
|
+
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
84
|
+
end
|
85
|
+
|
86
|
+
When /^I insert the anti\-CSRF middleware with the :check_only option$/ do |table|
|
87
|
+
must_be_checked = table.hashes.collect {|t| t.values}.flatten
|
88
|
+
@rack_builder.use Rack::Csrf, :check_only => must_be_checked
|
89
|
+
@app = toy_app
|
90
|
+
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
91
|
+
end
|
92
|
+
|
69
93
|
Then /^I get a fully functional rack$/ do
|
70
94
|
expect {Rack::MockRequest.new(@app).get('/')}.to_not raise_exception
|
71
95
|
end
|
@@ -1,12 +1,17 @@
|
|
1
1
|
Feature: Customization of the field name
|
2
2
|
|
3
|
-
|
3
|
+
Background:
|
4
4
|
Given a rack with the anti-CSRF middleware and the :field option
|
5
|
-
|
5
|
+
|
6
|
+
Scenario: GET request with the right CSRF token in custom field
|
7
|
+
When it receives a GET request with the right CSRF token
|
8
|
+
Then it lets it pass untouched
|
9
|
+
|
10
|
+
Scenario: GET request with the wrong CSRF token in custom field
|
11
|
+
When it receives a GET request with the wrong CSRF token
|
6
12
|
Then it lets it pass untouched
|
7
13
|
|
8
14
|
Scenario Outline: Handling request with the right CSRF token in custom field
|
9
|
-
Given a rack with the anti-CSRF middleware and the :field option
|
10
15
|
When it receives a <method> request with the right CSRF token
|
11
16
|
Then it lets it pass untouched
|
12
17
|
|
@@ -18,7 +23,6 @@ Feature: Customization of the field name
|
|
18
23
|
| PATCH |
|
19
24
|
|
20
25
|
Scenario Outline: Handling request with the wrong CSRF token in custom field
|
21
|
-
Given a rack with the anti-CSRF middleware and the :field option
|
22
26
|
When it receives a <method> request with the wrong CSRF token
|
23
27
|
Then it responds with 403
|
24
28
|
And the response body is empty
|
@@ -1,12 +1,17 @@
|
|
1
1
|
Feature: Customization of the key name
|
2
2
|
|
3
|
-
|
3
|
+
Background:
|
4
4
|
Given a rack with the anti-CSRF middleware and the :key option
|
5
|
-
|
5
|
+
|
6
|
+
Scenario: GET request with the right CSRF token stored in custom key
|
7
|
+
When it receives a GET request with the right CSRF token
|
8
|
+
Then it lets it pass untouched
|
9
|
+
|
10
|
+
Scenario: GET request with the wrong CSRF token stored in custom key
|
11
|
+
When it receives a GET request with the wrong CSRF token
|
6
12
|
Then it lets it pass untouched
|
7
13
|
|
8
14
|
Scenario Outline: Handling request with the right CSRF token stored in custom key
|
9
|
-
Given a rack with the anti-CSRF middleware and the :key option
|
10
15
|
When it receives a <method> request with the right CSRF token
|
11
16
|
Then it lets it pass untouched
|
12
17
|
|
@@ -18,7 +23,6 @@ Feature: Customization of the key name
|
|
18
23
|
| PATCH |
|
19
24
|
|
20
25
|
Scenario Outline: Handling request with the wrong CSRF token stored in custom key
|
21
|
-
Given a rack with the anti-CSRF middleware and the :key option
|
22
26
|
When it receives a <method> request with the wrong CSRF token
|
23
27
|
Then it responds with 403
|
24
28
|
And the response body is empty
|
data/lib/rack/csrf.rb
CHANGED
@@ -17,22 +17,25 @@ module Rack
|
|
17
17
|
@app = app
|
18
18
|
|
19
19
|
@raisable = opts[:raise] || false
|
20
|
-
@
|
20
|
+
@to_be_skipped = (opts[:skip] || []).map {|r| /\A#{r}\Z/i}
|
21
|
+
@to_be_checked = (opts[:check_only] || []).map {|r| /\A#{r}\Z/i}
|
21
22
|
@@field = opts[:field] if opts[:field]
|
22
23
|
@@key = opts[:key] if opts[:key]
|
23
24
|
|
24
|
-
|
25
|
+
standard_http_methods = %w(POST PUT DELETE PATCH)
|
26
|
+
check_also = opts[:check_also] || []
|
27
|
+
@http_methods = (standard_http_methods + check_also).flatten.uniq
|
25
28
|
end
|
26
29
|
|
27
30
|
def call(env)
|
28
31
|
unless env['rack.session']
|
29
32
|
raise SessionUnavailable.new('Rack::Csrf depends on session middleware')
|
30
33
|
end
|
31
|
-
self.class.
|
34
|
+
self.class.token(env)
|
32
35
|
req = Rack::Request.new(env)
|
33
|
-
untouchable =
|
34
|
-
req.
|
35
|
-
|
36
|
+
untouchable = skip_checking(req) ||
|
37
|
+
!@http_methods.include?(req.request_method) ||
|
38
|
+
req.params[self.class.field] == env['rack.session'][self.class.key]
|
36
39
|
if untouchable
|
37
40
|
@app.call(env)
|
38
41
|
else
|
@@ -41,34 +44,40 @@ module Rack
|
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
44
|
-
def self.
|
47
|
+
def self.key
|
45
48
|
@@key
|
46
49
|
end
|
47
50
|
|
48
|
-
def self.
|
51
|
+
def self.field
|
49
52
|
@@field
|
50
53
|
end
|
51
54
|
|
52
|
-
def self.
|
53
|
-
env['rack.session'][
|
55
|
+
def self.token(env)
|
56
|
+
env['rack.session'][key] ||= SecureRandom.base64(32)
|
54
57
|
end
|
55
58
|
|
56
|
-
def self.
|
57
|
-
%Q(<input type="hidden" name="#{
|
59
|
+
def self.tag(env)
|
60
|
+
%Q(<input type="hidden" name="#{field}" value="#{token(env)}" />)
|
58
61
|
end
|
59
62
|
|
60
63
|
class << self
|
61
|
-
alias_method :
|
62
|
-
alias_method :
|
63
|
-
alias_method :
|
64
|
-
alias_method :
|
64
|
+
alias_method :csrf_key, :key
|
65
|
+
alias_method :csrf_field, :field
|
66
|
+
alias_method :csrf_token, :token
|
67
|
+
alias_method :csrf_tag, :tag
|
65
68
|
end
|
66
69
|
|
67
70
|
protected
|
68
71
|
|
69
72
|
def skip_checking request
|
73
|
+
skip = any? @to_be_skipped, request
|
74
|
+
allow = any? @to_be_checked, request
|
75
|
+
skip || (!@to_be_checked.empty? && !allow)
|
76
|
+
end
|
77
|
+
|
78
|
+
def any? list, request
|
70
79
|
pi = request.path_info.empty? ? '/' : request.path_info
|
71
|
-
|
80
|
+
list.any? do |route|
|
72
81
|
route =~ (request.request_method + ':' + pi)
|
73
82
|
end
|
74
83
|
end
|
data/rack_csrf.gemspec
CHANGED
@@ -4,14 +4,14 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "2.
|
7
|
+
s.name = "rack_csrf"
|
8
|
+
s.version = "2.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Emanuele Vicentini"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
12
|
+
s.date = "2011-10-23"
|
13
|
+
s.description = "Anti-CSRF Rack middleware"
|
14
|
+
s.email = "emanuele.vicentini@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE.rdoc",
|
17
17
|
"README.rdoc"
|
@@ -28,6 +28,14 @@ Gem::Specification.new do |s|
|
|
28
28
|
"examples/camping/README.rdoc",
|
29
29
|
"examples/camping/app.rb",
|
30
30
|
"examples/camping/config.ru",
|
31
|
+
"examples/cuba/Gemfile",
|
32
|
+
"examples/cuba/README.rdoc",
|
33
|
+
"examples/cuba/app.rb",
|
34
|
+
"examples/cuba/config-with-raise.ru",
|
35
|
+
"examples/cuba/config.ru",
|
36
|
+
"examples/cuba/views/form.erb",
|
37
|
+
"examples/cuba/views/form_not_working.erb",
|
38
|
+
"examples/cuba/views/response.erb",
|
31
39
|
"examples/innate/Gemfile",
|
32
40
|
"examples/innate/README.rdoc",
|
33
41
|
"examples/innate/app.rb",
|
@@ -49,7 +57,10 @@ Gem::Specification.new do |s|
|
|
49
57
|
"examples/sinatra/views/form.erb",
|
50
58
|
"examples/sinatra/views/form_not_working.erb",
|
51
59
|
"examples/sinatra/views/response.erb",
|
60
|
+
"features/check_only_some_specific_requests.feature",
|
61
|
+
"features/custom_http_methods.feature",
|
52
62
|
"features/empty_responses.feature",
|
63
|
+
"features/inspecting_also_get_requests.feature",
|
53
64
|
"features/raising_exception.feature",
|
54
65
|
"features/setup.feature",
|
55
66
|
"features/skip_some_routes.feature",
|
@@ -66,13 +77,13 @@ Gem::Specification.new do |s|
|
|
66
77
|
"spec/csrf_spec.rb",
|
67
78
|
"spec/spec_helper.rb"
|
68
79
|
]
|
69
|
-
s.homepage =
|
80
|
+
s.homepage = "https://github.com/baldowl/rack_csrf"
|
70
81
|
s.licenses = ["MIT"]
|
71
|
-
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Csrf 2.
|
82
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Csrf 2.3.0", "--main", "README.rdoc"]
|
72
83
|
s.require_paths = ["lib"]
|
73
|
-
s.rubyforge_project =
|
74
|
-
s.rubygems_version =
|
75
|
-
s.summary =
|
84
|
+
s.rubyforge_project = "rackcsrf"
|
85
|
+
s.rubygems_version = "1.8.11"
|
86
|
+
s.summary = "Anti-CSRF Rack middleware"
|
76
87
|
|
77
88
|
if s.respond_to? :specification_version then
|
78
89
|
s.specification_version = 3
|
@@ -82,17 +93,20 @@ Gem::Specification.new do |s|
|
|
82
93
|
s.add_development_dependency(%q<cucumber>, [">= 0.1.13"])
|
83
94
|
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
84
95
|
s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
|
96
|
+
s.add_development_dependency(%q<rdoc>, [">= 2.4.2"])
|
85
97
|
else
|
86
98
|
s.add_dependency(%q<rack>, [">= 0.9"])
|
87
99
|
s.add_dependency(%q<cucumber>, [">= 0.1.13"])
|
88
100
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
89
101
|
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
102
|
+
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
90
103
|
end
|
91
104
|
else
|
92
105
|
s.add_dependency(%q<rack>, [">= 0.9"])
|
93
106
|
s.add_dependency(%q<cucumber>, [">= 0.1.13"])
|
94
107
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
95
108
|
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
109
|
+
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
96
110
|
end
|
97
111
|
end
|
98
112
|
|
data/spec/csrf_spec.rb
CHANGED
@@ -1,46 +1,46 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
2
|
|
3
3
|
describe Rack::Csrf do
|
4
|
-
describe '
|
4
|
+
describe 'key' do
|
5
5
|
it "should be 'csrf.token' by default" do
|
6
|
-
Rack::Csrf.
|
6
|
+
Rack::Csrf.key.should == 'csrf.token'
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should be the value of the :key option" do
|
10
10
|
fakeapp = lambda {|env| [200, {}, []]}
|
11
11
|
Rack::Csrf.new fakeapp, :key => 'whatever'
|
12
|
-
Rack::Csrf.
|
12
|
+
Rack::Csrf.key.should == 'whatever'
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe '
|
17
|
-
it 'should be the same as
|
18
|
-
Rack::Csrf.method(:
|
16
|
+
describe 'csrf_key' do
|
17
|
+
it 'should be the same as method key' do
|
18
|
+
Rack::Csrf.method(:csrf_key).should == Rack::Csrf.method(:key)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe '
|
22
|
+
describe 'field' do
|
23
23
|
it "should be '_csrf' by default" do
|
24
|
-
Rack::Csrf.
|
24
|
+
Rack::Csrf.field.should == '_csrf'
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should be the value of :field option" do
|
28
28
|
fakeapp = lambda {|env| [200, {}, []]}
|
29
29
|
Rack::Csrf.new fakeapp, :field => 'whatever'
|
30
|
-
Rack::Csrf.
|
30
|
+
Rack::Csrf.field.should == 'whatever'
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
describe '
|
35
|
-
it 'should be the same as
|
36
|
-
Rack::Csrf.method(:
|
34
|
+
describe 'csrf_field' do
|
35
|
+
it 'should be the same as method field' do
|
36
|
+
Rack::Csrf.method(:csrf_field).should == Rack::Csrf.method(:field)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
describe '
|
40
|
+
describe 'token(env)' do
|
41
41
|
let(:env) { {'rack.session' => {}} }
|
42
42
|
|
43
|
-
specify {Rack::Csrf.
|
43
|
+
specify {Rack::Csrf.token(env).should have_at_least(32).characters}
|
44
44
|
|
45
45
|
context 'when accessing/manipulating the session' do
|
46
46
|
before do
|
@@ -48,45 +48,45 @@ describe Rack::Csrf do
|
|
48
48
|
Rack::Csrf.new fakeapp, :key => 'whatever'
|
49
49
|
end
|
50
50
|
|
51
|
-
it 'should use the key provided by
|
51
|
+
it 'should use the key provided by method key' do
|
52
52
|
env['rack.session'].should be_empty
|
53
|
-
Rack::Csrf.
|
54
|
-
env['rack.session'][Rack::Csrf.
|
53
|
+
Rack::Csrf.token env
|
54
|
+
env['rack.session'][Rack::Csrf.key].should_not be_nil
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'when the session does not already contain the token' do
|
59
59
|
it 'should store the token inside the session' do
|
60
60
|
env['rack.session'].should be_empty
|
61
|
-
|
62
|
-
|
61
|
+
token = Rack::Csrf.token(env)
|
62
|
+
token.should == env['rack.session'][Rack::Csrf.key]
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
66
|
context 'when the session already contains the token' do
|
67
67
|
before do
|
68
|
-
Rack::Csrf.
|
68
|
+
Rack::Csrf.token env
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'should get the token from the session' do
|
72
|
-
env['rack.session'][Rack::Csrf.
|
72
|
+
env['rack.session'][Rack::Csrf.key].should == Rack::Csrf.token(env)
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
describe '
|
78
|
-
it 'should be the same as
|
79
|
-
Rack::Csrf.method(:
|
77
|
+
describe 'csrf_token(env)' do
|
78
|
+
it 'should be the same as method token(env)' do
|
79
|
+
Rack::Csrf.method(:csrf_token).should == Rack::Csrf.method(:token)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
describe '
|
83
|
+
describe 'tag(env)' do
|
84
84
|
let(:env) { {'rack.session' => {}} }
|
85
85
|
|
86
86
|
let :tag do
|
87
87
|
fakeapp = lambda {|env| [200, {}, []]}
|
88
88
|
Rack::Csrf.new fakeapp, :field => 'whatever'
|
89
|
-
Rack::Csrf.
|
89
|
+
Rack::Csrf.tag env
|
90
90
|
end
|
91
91
|
|
92
92
|
it 'should be an input field' do
|
@@ -97,19 +97,96 @@ describe Rack::Csrf do
|
|
97
97
|
tag.should =~ /type="hidden"/
|
98
98
|
end
|
99
99
|
|
100
|
-
it "should have the
|
101
|
-
tag.should =~ /name="#{Rack::Csrf.
|
100
|
+
it "should have the name provided by method field" do
|
101
|
+
tag.should =~ /name="#{Rack::Csrf.field}"/
|
102
102
|
end
|
103
103
|
|
104
|
-
it "should have the
|
105
|
-
quoted_value = Regexp.quote %Q(value="#{Rack::Csrf.
|
104
|
+
it "should have the value provided by method token(env)" do
|
105
|
+
quoted_value = Regexp.quote %Q(value="#{Rack::Csrf.token(env)}")
|
106
106
|
tag.should =~ /#{quoted_value}/
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
describe '
|
111
|
-
it 'should be the same as
|
112
|
-
Rack::Csrf.method(:
|
110
|
+
describe 'csrf_tag(env)' do
|
111
|
+
it 'should be the same as method tag(env)' do
|
112
|
+
Rack::Csrf.method(:csrf_tag).should == Rack::Csrf.method(:tag)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'skip_checking' do
|
117
|
+
class MockReq
|
118
|
+
attr_accessor :path_info, :request_method
|
119
|
+
end
|
120
|
+
|
121
|
+
before :each do
|
122
|
+
@request = MockReq.new
|
123
|
+
@request.path_info = '/hello'
|
124
|
+
@request.request_method = 'POST'
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'with empty :skip and :check_only lists' do
|
128
|
+
let(:csrf) { Rack::Csrf.new nil }
|
129
|
+
|
130
|
+
it 'should run the check, irrespective of the request' do
|
131
|
+
csrf.send(:skip_checking, @request).should be_false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'with routes in the :skip list and nothing in the :check_only list' do
|
136
|
+
let(:csrf) { Rack::Csrf.new nil, :skip => ['POST:/hello'] }
|
137
|
+
|
138
|
+
it 'should skip the check when the request is included in the :skip list' do
|
139
|
+
csrf.send(:skip_checking, @request).should be_true
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should run the check when the request is not in the :skip list' do
|
143
|
+
@request.path_info = '/byebye'
|
144
|
+
csrf.send(:skip_checking, @request).should be_false
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with routes in the :check_only list and nothing in the :skip list' do
|
149
|
+
let(:csrf) { Rack::Csrf.new nil, :check_only => ['POST:/hello'] }
|
150
|
+
|
151
|
+
it 'should run the check when the request is included in the :check_only list' do
|
152
|
+
csrf.send(:skip_checking, @request).should be_false
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should skip the check when the request is not in the :check_only list' do
|
156
|
+
@request.path_info = '/byebye'
|
157
|
+
csrf.send(:skip_checking, @request).should be_true
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'with different routes in the :skip and :check_only lists' do
|
162
|
+
let :csrf do
|
163
|
+
Rack::Csrf.new nil,
|
164
|
+
:skip => ['POST:/hello'],
|
165
|
+
:check_only => ['POST:/byebye']
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'should skip the check when the request is included in the :skip list' do
|
169
|
+
csrf.send(:skip_checking, @request).should be_true
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should run the check when the request is included in the :check_only list' do
|
173
|
+
@request.path_info = '/byebye'
|
174
|
+
csrf.send(:skip_checking, @request).should be_false
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'with the same routes in the :check_only and :skip lists' do
|
179
|
+
let :csrf do
|
180
|
+
Rack::Csrf.new nil,
|
181
|
+
:skip => ['POST:/hello'],
|
182
|
+
:check_only => ['POST:/hello']
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'when the request is included in one of the list' do
|
186
|
+
it 'should ignore the :check_only list and skip the check' do
|
187
|
+
csrf.send(:skip_checking, @request).should be_true
|
188
|
+
end
|
189
|
+
end
|
113
190
|
end
|
114
191
|
end
|
115
192
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack_csrf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 2.
|
10
|
+
version: 2.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Emanuele Vicentini
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-10-23 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rack
|
@@ -78,6 +78,22 @@ dependencies:
|
|
78
78
|
version: 2.0.0
|
79
79
|
type: :development
|
80
80
|
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rdoc
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 27
|
90
|
+
segments:
|
91
|
+
- 2
|
92
|
+
- 4
|
93
|
+
- 2
|
94
|
+
version: 2.4.2
|
95
|
+
type: :development
|
96
|
+
version_requirements: *id005
|
81
97
|
description: Anti-CSRF Rack middleware
|
82
98
|
email: emanuele.vicentini@gmail.com
|
83
99
|
executables: []
|
@@ -99,6 +115,14 @@ files:
|
|
99
115
|
- examples/camping/README.rdoc
|
100
116
|
- examples/camping/app.rb
|
101
117
|
- examples/camping/config.ru
|
118
|
+
- examples/cuba/Gemfile
|
119
|
+
- examples/cuba/README.rdoc
|
120
|
+
- examples/cuba/app.rb
|
121
|
+
- examples/cuba/config-with-raise.ru
|
122
|
+
- examples/cuba/config.ru
|
123
|
+
- examples/cuba/views/form.erb
|
124
|
+
- examples/cuba/views/form_not_working.erb
|
125
|
+
- examples/cuba/views/response.erb
|
102
126
|
- examples/innate/Gemfile
|
103
127
|
- examples/innate/README.rdoc
|
104
128
|
- examples/innate/app.rb
|
@@ -120,7 +144,10 @@ files:
|
|
120
144
|
- examples/sinatra/views/form.erb
|
121
145
|
- examples/sinatra/views/form_not_working.erb
|
122
146
|
- examples/sinatra/views/response.erb
|
147
|
+
- features/check_only_some_specific_requests.feature
|
148
|
+
- features/custom_http_methods.feature
|
123
149
|
- features/empty_responses.feature
|
150
|
+
- features/inspecting_also_get_requests.feature
|
124
151
|
- features/raising_exception.feature
|
125
152
|
- features/setup.feature
|
126
153
|
- features/skip_some_routes.feature
|
@@ -136,7 +163,7 @@ files:
|
|
136
163
|
- rack_csrf.gemspec
|
137
164
|
- spec/csrf_spec.rb
|
138
165
|
- spec/spec_helper.rb
|
139
|
-
homepage:
|
166
|
+
homepage: https://github.com/baldowl/rack_csrf
|
140
167
|
licenses:
|
141
168
|
- MIT
|
142
169
|
post_install_message:
|
@@ -144,7 +171,7 @@ rdoc_options:
|
|
144
171
|
- --line-numbers
|
145
172
|
- --inline-source
|
146
173
|
- --title
|
147
|
-
- Rack::Csrf 2.
|
174
|
+
- Rack::Csrf 2.3.0
|
148
175
|
- --main
|
149
176
|
- README.rdoc
|
150
177
|
require_paths:
|
@@ -170,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
197
|
requirements: []
|
171
198
|
|
172
199
|
rubyforge_project: rackcsrf
|
173
|
-
rubygems_version: 1.
|
200
|
+
rubygems_version: 1.8.11
|
174
201
|
signing_key:
|
175
202
|
specification_version: 3
|
176
203
|
summary: Anti-CSRF Rack middleware
|