rack_csrf 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.md +13 -0
- data/LICENSE.rdoc +1 -1
- data/README.rdoc +17 -15
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/examples/camping/Gemfile +4 -0
- data/examples/camping/README.rdoc +4 -4
- data/examples/innate/Gemfile +3 -0
- data/examples/innate/README.rdoc +5 -5
- data/examples/rack/Gemfile +3 -0
- data/examples/rack/README.rdoc +5 -5
- data/examples/sinatra/Gemfile +3 -0
- data/examples/sinatra/README.rdoc +6 -5
- data/features/empty_responses.feature +3 -0
- data/features/raising_exception.feature +3 -0
- data/features/skip_some_routes.feature +28 -0
- data/features/step_definitions/request_steps.rb +12 -4
- data/features/step_definitions/response_steps.rb +1 -2
- data/features/step_definitions/setup_steps.rb +10 -8
- data/features/variation_on_field_name.feature +2 -0
- data/features/variation_on_key_name.feature +2 -0
- data/lib/rack/csrf.rb +10 -2
- data/rack_csrf.gemspec +54 -50
- data/spec/csrf_spec.rb +28 -8
- metadata +13 -12
data/Changelog.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# v2.2.0 (2011-04-12)
|
2
|
+
|
3
|
+
* Simplified specs and some Cucumber's steps.
|
4
|
+
* Added handling of empty PATH_INFO.
|
5
|
+
* Added Gemfiles to the examples. Tweaked the READMEs.
|
6
|
+
* Extended API: added shorter aliases for the public methods.
|
7
|
+
* Tweaked example groups' names.
|
8
|
+
* Added support for PATCH verb.
|
9
|
+
* Added license metadata to gemspec via Jeweler's task.
|
10
|
+
* Replace lambdas with expect()... RSpec's white magic!
|
11
|
+
|
12
|
+
|
13
|
+
|
1
14
|
# v2.1.0 (2010-10-11)
|
2
15
|
|
3
16
|
* Tiny improvements to Rakefile.
|
data/LICENSE.rdoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
(The MIT License)
|
4
4
|
|
5
|
-
Copyright (c) 2009, 2010 Emanuele Vicentini
|
5
|
+
Copyright (c) 2009, 2010, 2011 Emanuele Vicentini
|
6
6
|
|
7
7
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
8
|
of this software and associated documentation files (the 'Software'), to deal
|
data/README.rdoc
CHANGED
@@ -12,11 +12,11 @@ with your preferred Rack-based framework.
|
|
12
12
|
First of all, beyond Rack itself, there is only one prerequisite: you must set
|
13
13
|
up your rack with a session middleware, inserted anywhere before Rack::Csrf.
|
14
14
|
|
15
|
-
Every POST, PUT and
|
16
|
-
token, randomly generated by Rack::Csrf and stored inside the
|
17
|
-
there's a token and it matches with the stored one, then the
|
18
|
-
over to the next rack component; if not, Rack::Csrf
|
19
|
-
an empty response.
|
15
|
+
Every POST, PUT, DELETE and PATCH request will be searched for the
|
16
|
+
anti-forging token, randomly generated by Rack::Csrf and stored inside the
|
17
|
+
session. If there's a token and it matches with the stored one, then the
|
18
|
+
request is handed over to the next rack component; if not, Rack::Csrf
|
19
|
+
immediately replies with an empty response.
|
20
20
|
|
21
21
|
I have not tested Rack::Csrf with Rack 0.4.0 or earlier versions, but it could
|
22
22
|
possibly work.
|
@@ -35,15 +35,16 @@ The following options allow you to tweak Rack::Csrf.
|
|
35
35
|
Default value: false.
|
36
36
|
|
37
37
|
[<tt>:skip</tt>]
|
38
|
-
By default, Rack::Csrf checks every POST, PUT and
|
39
|
-
array of HTTP method/URL (regular expressions allowed) to this
|
40
|
-
can choose what to let pass unchecked:
|
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 choose what to let pass unchecked:
|
41
41
|
|
42
42
|
use Rack::Csrf, :skip => ['POST:/not_checking', 'PUT:/me_too',
|
43
|
-
'DELETE:/cars/.*\.xml']
|
43
|
+
'DELETE:/cars/.*\.xml', 'PATCH:/this/.*/too']
|
44
44
|
|
45
45
|
Please, note that the regular expressions are not escaped and it is your
|
46
|
-
duty to write them correctly.
|
46
|
+
duty to write them correctly. Empty PATH_INFO (see Rack's spec for details)
|
47
|
+
is treated as '/' for this check.
|
47
48
|
|
48
49
|
Default value: empty.
|
49
50
|
|
@@ -79,19 +80,19 @@ The ill devised <tt>:browser_only</tt> option could have been used to
|
|
79
80
|
The following class methods try to ease the insertion of the anti-forging
|
80
81
|
token.
|
81
82
|
|
82
|
-
[<tt>Rack::Csrf.csrf_key</tt>]
|
83
|
+
[<tt>Rack::Csrf.csrf_key</tt> (also <tt>Rack::Csrf.key</tt>)]
|
83
84
|
Returns the name of the key used to store/retrieve the token from the Rack
|
84
85
|
session.
|
85
86
|
|
86
|
-
[<tt>Rack::Csrf.csrf_field</tt>]
|
87
|
+
[<tt>Rack::Csrf.csrf_field</tt> (also <tt>Rack::Csrf.field</tt>)]
|
87
88
|
Returns the name of the field that must be present in the request.
|
88
89
|
|
89
|
-
[<tt>Rack::Csrf.csrf_token(env)</tt>]
|
90
|
+
[<tt>Rack::Csrf.csrf_token(env)</tt> (also <tt>Rack::Csrf.token(env)</tt>)]
|
90
91
|
Given the request's environment, it generates a random token, stuffs it in
|
91
92
|
the session and returns it to the caller or simply retrieves the already
|
92
93
|
stored one.
|
93
94
|
|
94
|
-
[<tt>Rack::Csrf.csrf_tag(env)</tt>]
|
95
|
+
[<tt>Rack::Csrf.csrf_tag(env)</tt> (also <tt>Rack::Csrf.tag(env)</tt>)]
|
95
96
|
Given the request's environment, it generates a small HTML fragment to
|
96
97
|
insert the token in a standard form like an hidden input field with the
|
97
98
|
right value already entered for you.
|
@@ -124,4 +125,5 @@ forgo responsibilities for keeping your application as safe as possible.
|
|
124
125
|
|
125
126
|
== Copyright
|
126
127
|
|
127
|
-
Copyright (c) 2009, 2010 Emanuele Vicentini. See LICENSE.rdoc for
|
128
|
+
Copyright (c) 2009, 2010, 2011 Emanuele Vicentini. See LICENSE.rdoc for
|
129
|
+
details.
|
data/Rakefile
CHANGED
@@ -25,9 +25,10 @@ Jeweler::Tasks.new do |gem|
|
|
25
25
|
gem.name = 'rack_csrf'
|
26
26
|
gem.summary = 'Anti-CSRF Rack middleware'
|
27
27
|
gem.description = 'Anti-CSRF Rack middleware'
|
28
|
+
gem.license = 'MIT'
|
29
|
+
gem.authors = 'Emanuele Vicentini'
|
28
30
|
gem.email = 'emanuele.vicentini@gmail.com'
|
29
31
|
gem.homepage = 'http://github.com/baldowl/rack_csrf'
|
30
|
-
gem.authors = ['Emanuele Vicentini']
|
31
32
|
gem.rubyforge_project = 'rackcsrf'
|
32
33
|
gem.add_dependency 'rack', '>= 0.9'
|
33
34
|
gem.add_development_dependency 'cucumber', '>= 0.1.13'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.2.0
|
@@ -1,10 +1,10 @@
|
|
1
1
|
= How to use Rack::Csrf with Camping
|
2
2
|
|
3
3
|
This Camping application has been provided by David Susco. All you need is
|
4
|
-
Camping itself and Markaby
|
4
|
+
Camping itself and Markaby, so, assuming you have Bundler installed, run:
|
5
5
|
|
6
|
-
$
|
7
|
-
$ camping -p 3000 app.rb
|
6
|
+
$ bundle install
|
7
|
+
$ bundle exec camping -p 3000 app.rb
|
8
8
|
|
9
9
|
The <tt>config.ru</tt> can be used to run the application with any
|
10
10
|
Rack-compliant web server.
|
@@ -13,4 +13,4 @@ Please, note the way Rack::Csrf has been inserted into the stack and the
|
|
13
13
|
position relative to Camping::Session (see Camping's internals for the
|
14
14
|
reason).
|
15
15
|
|
16
|
-
Tested with Camping
|
16
|
+
Tested with Camping and Markaby versions listed in the Gemfile.
|
data/examples/innate/README.rdoc
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
= How to use Rack::Csrf with Innate
|
2
2
|
|
3
3
|
These are two mini, slightly different, Innate applications. You only need
|
4
|
-
Innate to try them
|
4
|
+
Innate to try them, so, assuming you have Bundler installed, run:
|
5
5
|
|
6
|
-
$
|
7
|
-
$ ruby start.rb
|
8
|
-
$ ruby start-with-raise.rb
|
6
|
+
$ bundle install
|
7
|
+
$ bundle exec ruby start.rb
|
8
|
+
$ bundle exec ruby start-with-raise.rb
|
9
9
|
|
10
|
-
Tested with Innate
|
10
|
+
Tested with Innate versions listed in the Gemfile.
|
11
11
|
|
12
12
|
Please, note that Innate is, to some extent, the kernel of Ramaze; "upgrading"
|
13
13
|
these examples to use Ramaze is left as an exercise to the reader :-)
|
data/examples/rack/README.rdoc
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
= How to use Rack::Csrf with Rack
|
2
2
|
|
3
3
|
This is a mini Rack application with two slightly different rackup files. You
|
4
|
-
only need Rack to try them
|
4
|
+
only need Rack to try them, so, assuming you have Bundler installed, run:
|
5
5
|
|
6
|
-
$
|
7
|
-
$
|
8
|
-
$
|
6
|
+
$ bundle install
|
7
|
+
$ bundle exec rackup -p 3000 config.ru
|
8
|
+
$ bundle exec rackup -p 3000 config-with-raise.ru
|
9
9
|
|
10
|
-
Tested with Rack
|
10
|
+
Tested with Rack versions listed in the Gemfile.
|
@@ -1,10 +1,11 @@
|
|
1
1
|
= How to use Rack::Csrf with Sinatra
|
2
2
|
|
3
3
|
This is a mini Sinatra application with two slightly different rackup files.
|
4
|
-
Beside Rack you only need Sinatra to try them
|
4
|
+
Beside Rack you only need Sinatra to try them, so, assuming you have Bundler
|
5
|
+
installed, run:
|
5
6
|
|
6
|
-
$
|
7
|
-
$
|
8
|
-
$
|
7
|
+
$ bundle install
|
8
|
+
$ bundle exec rackup -p 3000 config.ru
|
9
|
+
$ bundle exec rackup -p 3000 config-with-raise.ru
|
9
10
|
|
10
|
-
Tested with Sinatra
|
11
|
+
Tested with Sinatra versions listed in the Gemfile.
|
@@ -21,6 +21,7 @@ Feature: Handling of the HTTP requests returning an empty response
|
|
21
21
|
| POST |
|
22
22
|
| PUT |
|
23
23
|
| DELETE |
|
24
|
+
| PATCH |
|
24
25
|
|
25
26
|
Scenario Outline: Handling request with the right CSRF token
|
26
27
|
Given a rack with the anti-CSRF middleware
|
@@ -32,6 +33,7 @@ Feature: Handling of the HTTP requests returning an empty response
|
|
32
33
|
| POST |
|
33
34
|
| PUT |
|
34
35
|
| DELETE |
|
36
|
+
| PATCH |
|
35
37
|
|
36
38
|
Scenario Outline: Handling request with the wrong CSRF token
|
37
39
|
Given a rack with the anti-CSRF middleware
|
@@ -44,3 +46,4 @@ Feature: Handling of the HTTP requests returning an empty response
|
|
44
46
|
| POST |
|
45
47
|
| PUT |
|
46
48
|
| DELETE |
|
49
|
+
| PATCH |
|
@@ -16,6 +16,7 @@ Feature: Handling of the HTTP requests raising an exception
|
|
16
16
|
| POST |
|
17
17
|
| PUT |
|
18
18
|
| DELETE |
|
19
|
+
| PATCH |
|
19
20
|
|
20
21
|
Scenario Outline: Handling request with the right CSRF token
|
21
22
|
Given a rack with the anti-CSRF middleware and the :raise option
|
@@ -27,6 +28,7 @@ Feature: Handling of the HTTP requests raising an exception
|
|
27
28
|
| POST |
|
28
29
|
| PUT |
|
29
30
|
| DELETE |
|
31
|
+
| PATCH |
|
30
32
|
|
31
33
|
Scenario Outline: Handling request with the wrong CSRF token
|
32
34
|
Given a rack with the anti-CSRF middleware and the :raise option
|
@@ -39,3 +41,4 @@ Feature: Handling of the HTTP requests raising an exception
|
|
39
41
|
| POST |
|
40
42
|
| PUT |
|
41
43
|
| DELETE |
|
44
|
+
| PATCH |
|
@@ -7,6 +7,7 @@ Feature: Skipping the check for some specific routes
|
|
7
7
|
| PUT:/is_wrong |
|
8
8
|
| POST:/not_.*\.json |
|
9
9
|
| DELETE:/cars/.*\.xml |
|
10
|
+
| PATCH:/this/one/too |
|
10
11
|
When it receives a <method> request for <path> without the CSRF token
|
11
12
|
Then it lets it pass untouched
|
12
13
|
|
@@ -17,6 +18,7 @@ Feature: Skipping the check for some specific routes
|
|
17
18
|
| POST | /not_checking.json |
|
18
19
|
| POST | /not_again/params/whatever.json |
|
19
20
|
| DELETE | /cars/abc123.xml |
|
21
|
+
| PATCH | /this/one/too |
|
20
22
|
|
21
23
|
Scenario Outline: Keep checking the requests for other method/path pairs
|
22
24
|
Given a rack with the anti-CSRF middleware and the :skip option
|
@@ -25,6 +27,7 @@ Feature: Skipping the check for some specific routes
|
|
25
27
|
| PUT:/is_wrong |
|
26
28
|
| POST:/not_.*\.json |
|
27
29
|
| DELETE:/cars/.*\.xml |
|
30
|
+
| PATCH:/this/one/too |
|
28
31
|
When it receives a <method> request for <path> without the CSRF token
|
29
32
|
Then it responds with 403
|
30
33
|
And the response body is empty
|
@@ -33,14 +36,39 @@ Feature: Skipping the check for some specific routes
|
|
33
36
|
| method | path |
|
34
37
|
| PUT | /not_checking |
|
35
38
|
| DELETE | /not_checking |
|
39
|
+
| PATCH | /not_checking |
|
36
40
|
| POST | /is_wrong |
|
37
41
|
| DELETE | /is_wrong |
|
42
|
+
| PATCH | /is_wrong |
|
38
43
|
| POST | / |
|
39
44
|
| PUT | /not |
|
40
45
|
| POST | /is |
|
41
46
|
| PUT | /not_checking.json |
|
42
47
|
| DELETE | /not_checking.json |
|
48
|
+
| PATCH | /not_checking.json |
|
43
49
|
| PUT | /not_again/params/whatever.json |
|
44
50
|
| DELETE | /not_again/params/whatever.json |
|
51
|
+
| PATCH | /not_again/params/whatever.json |
|
45
52
|
| POST | /cars/abc123.xml |
|
46
53
|
| PUT | /cars/abc123.xml |
|
54
|
+
| PATCH | /cars/abc123.xml |
|
55
|
+
| POST | /this/one/too |
|
56
|
+
| PUT | /this/one/too |
|
57
|
+
| DELETE | /this/one/too |
|
58
|
+
|
59
|
+
Scenario Outline: Handling correctly empty PATH_INFO
|
60
|
+
Given a rack with the anti-CSRF middleware and the :skip option
|
61
|
+
| pair |
|
62
|
+
| POST:/ |
|
63
|
+
| PUT:/ |
|
64
|
+
| DELETE:/ |
|
65
|
+
| PATCH:/ |
|
66
|
+
When it receives a <method> request with neither PATH_INFO nor CSRF token
|
67
|
+
Then it lets it pass untouched
|
68
|
+
|
69
|
+
Examples:
|
70
|
+
| method |
|
71
|
+
| POST |
|
72
|
+
| PUT |
|
73
|
+
| DELETE |
|
74
|
+
| PATCH |
|
@@ -6,7 +6,7 @@ end
|
|
6
6
|
# Yes, they're not as DRY as possible, but I think they're more readable than
|
7
7
|
# a single step definition with a few captures and more complex checkings.
|
8
8
|
|
9
|
-
When /^it receives a (POST|PUT|DELETE) request without the CSRF token$/ do |http_method|
|
9
|
+
When /^it receives a (POST|PUT|DELETE|PATCH) request without the CSRF token$/ do |http_method|
|
10
10
|
begin
|
11
11
|
@browser.request '/', :method => http_method
|
12
12
|
rescue Exception => e
|
@@ -14,7 +14,7 @@ When /^it receives a (POST|PUT|DELETE) request without the CSRF token$/ do |http
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
When /^it receives a (POST|PUT|DELETE) request for (.+) without the CSRF token$/ do |http_method, path|
|
17
|
+
When /^it receives a (POST|PUT|DELETE|PATCH) request for (.+) without the CSRF token$/ do |http_method, path|
|
18
18
|
begin
|
19
19
|
@browser.request path, :method => http_method
|
20
20
|
rescue Exception => e
|
@@ -22,13 +22,13 @@ When /^it receives a (POST|PUT|DELETE) request for (.+) without the CSRF token$/
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
When /^it receives a (POST|PUT|DELETE) request with the right CSRF token$/ do |http_method|
|
25
|
+
When /^it receives a (POST|PUT|DELETE|PATCH) request with the right CSRF token$/ do |http_method|
|
26
26
|
@browser.request '/', :method => http_method,
|
27
27
|
'rack.session' => {Rack::Csrf.csrf_key => 'right_token'},
|
28
28
|
:params => {Rack::Csrf.csrf_field => 'right_token'}
|
29
29
|
end
|
30
30
|
|
31
|
-
When /^it receives a (POST|PUT|DELETE) request with the wrong CSRF token$/ do |http_method|
|
31
|
+
When /^it receives a (POST|PUT|DELETE|PATCH) request with the wrong CSRF token$/ do |http_method|
|
32
32
|
begin
|
33
33
|
@browser.request '/', :method => http_method,
|
34
34
|
:params => {Rack::Csrf.csrf_field => 'whatever'}
|
@@ -36,3 +36,11 @@ When /^it receives a (POST|PUT|DELETE) request with the wrong CSRF token$/ do |h
|
|
36
36
|
@exception = e
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
40
|
+
When /^it receives a (POST|PUT|DELETE|PATCH) request with neither PATH_INFO nor CSRF token$/ do |http_method|
|
41
|
+
begin
|
42
|
+
@browser.request '/doesntmatter', :method => http_method, 'PATH_INFO' => ''
|
43
|
+
rescue Exception => e
|
44
|
+
@exception = e
|
45
|
+
end
|
46
|
+
end
|
@@ -12,10 +12,9 @@ Then /^the response body is empty$/ do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
Then /^there is no response$/ do
|
15
|
-
|
15
|
+
expect {@browser.last_response}.to raise_exception(Rack::Test::Error)
|
16
16
|
end
|
17
17
|
|
18
18
|
Then /^an exception is climbing up the stack$/ do
|
19
|
-
@exception.should_not be_nil
|
20
19
|
@exception.should be_an_instance_of(Rack::Csrf::InvalidCsrfToken)
|
21
20
|
end
|
@@ -37,44 +37,46 @@ end
|
|
37
37
|
|
38
38
|
When /^I insert the anti\-CSRF middleware$/ do
|
39
39
|
@rack_builder.use Rack::Csrf
|
40
|
-
toy_app
|
40
|
+
@app = toy_app
|
41
41
|
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
42
42
|
end
|
43
43
|
|
44
44
|
When /^I insert the anti\-CSRF middleware with the :raise option$/ do
|
45
45
|
@rack_builder.use Rack::Csrf, :raise => true
|
46
|
-
toy_app
|
46
|
+
@app = toy_app
|
47
47
|
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
48
48
|
end
|
49
49
|
|
50
50
|
When /^I insert the anti\-CSRF middleware with the :skip option$/ do |table|
|
51
51
|
skippable = table.hashes.collect {|t| t.values}.flatten
|
52
52
|
@rack_builder.use Rack::Csrf, :skip => skippable
|
53
|
-
toy_app
|
53
|
+
@app = toy_app
|
54
54
|
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
55
55
|
end
|
56
56
|
|
57
57
|
When /^I insert the anti\-CSRF middleware with the :field option$/ do
|
58
58
|
@rack_builder.use Rack::Csrf, :field => 'fantasy_name'
|
59
|
-
toy_app
|
59
|
+
@app = toy_app
|
60
60
|
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
61
61
|
end
|
62
62
|
|
63
63
|
When /^I insert the anti\-CSRF middleware with the :key option$/ do
|
64
64
|
@rack_builder.use Rack::Csrf, :key => 'fantasy_name'
|
65
|
-
toy_app
|
65
|
+
@app = toy_app
|
66
66
|
@browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
|
67
67
|
end
|
68
68
|
|
69
69
|
Then /^I get a fully functional rack$/ do
|
70
|
-
|
70
|
+
expect {Rack::MockRequest.new(@app).get('/')}.to_not raise_exception
|
71
71
|
end
|
72
72
|
|
73
73
|
Then /^I get an error message$/ do
|
74
|
-
|
74
|
+
expect {Rack::MockRequest.new(@app).get('/')}.to raise_exception(
|
75
|
+
Rack::Csrf::SessionUnavailable,
|
76
|
+
'Rack::Csrf depends on session middleware')
|
75
77
|
end
|
76
78
|
|
77
79
|
def toy_app
|
78
80
|
@rack_builder.run(lambda {|env| Rack::Response.new('Hello world!').finish})
|
79
|
-
@
|
81
|
+
@rack_builder.to_app
|
80
82
|
end
|
@@ -15,6 +15,7 @@ Feature: Customization of the field name
|
|
15
15
|
| POST |
|
16
16
|
| PUT |
|
17
17
|
| DELETE |
|
18
|
+
| PATCH |
|
18
19
|
|
19
20
|
Scenario Outline: Handling request with the wrong CSRF token in custom field
|
20
21
|
Given a rack with the anti-CSRF middleware and the :field option
|
@@ -27,3 +28,4 @@ Feature: Customization of the field name
|
|
27
28
|
| POST |
|
28
29
|
| PUT |
|
29
30
|
| DELETE |
|
31
|
+
| PATCH |
|
@@ -15,6 +15,7 @@ Feature: Customization of the key name
|
|
15
15
|
| POST |
|
16
16
|
| PUT |
|
17
17
|
| DELETE |
|
18
|
+
| PATCH |
|
18
19
|
|
19
20
|
Scenario Outline: Handling request with the wrong CSRF token stored in custom key
|
20
21
|
Given a rack with the anti-CSRF middleware and the :key option
|
@@ -27,3 +28,4 @@ Feature: Customization of the key name
|
|
27
28
|
| POST |
|
28
29
|
| PUT |
|
29
30
|
| DELETE |
|
31
|
+
| PATCH |
|
data/lib/rack/csrf.rb
CHANGED
@@ -21,7 +21,7 @@ module Rack
|
|
21
21
|
@@field = opts[:field] if opts[:field]
|
22
22
|
@@key = opts[:key] if opts[:key]
|
23
23
|
|
24
|
-
@http_verbs = %w(POST PUT DELETE)
|
24
|
+
@http_verbs = %w(POST PUT DELETE PATCH)
|
25
25
|
end
|
26
26
|
|
27
27
|
def call(env)
|
@@ -57,11 +57,19 @@ module Rack
|
|
57
57
|
%Q(<input type="hidden" name="#{csrf_field}" value="#{csrf_token(env)}" />)
|
58
58
|
end
|
59
59
|
|
60
|
+
class << self
|
61
|
+
alias_method :key, :csrf_key
|
62
|
+
alias_method :field, :csrf_field
|
63
|
+
alias_method :token, :csrf_token
|
64
|
+
alias_method :tag, :csrf_tag
|
65
|
+
end
|
66
|
+
|
60
67
|
protected
|
61
68
|
|
62
69
|
def skip_checking request
|
70
|
+
pi = request.path_info.empty? ? '/' : request.path_info
|
63
71
|
@skippable.any? do |route|
|
64
|
-
route =~ (request.request_method + ':' +
|
72
|
+
route =~ (request.request_method + ':' + pi)
|
65
73
|
end
|
66
74
|
end
|
67
75
|
end
|
data/rack_csrf.gemspec
CHANGED
@@ -1,76 +1,80 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rack_csrf}
|
8
|
-
s.version = "2.
|
8
|
+
s.version = "2.2.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 = %q{
|
12
|
+
s.date = %q{2011-04-12}
|
13
13
|
s.description = %q{Anti-CSRF Rack middleware}
|
14
14
|
s.email = %q{emanuele.vicentini@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE.rdoc",
|
17
|
-
|
17
|
+
"README.rdoc"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".rspec",
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
21
|
+
"Changelog.md",
|
22
|
+
"LICENSE.rdoc",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"cucumber.yml",
|
27
|
+
"examples/camping/Gemfile",
|
28
|
+
"examples/camping/README.rdoc",
|
29
|
+
"examples/camping/app.rb",
|
30
|
+
"examples/camping/config.ru",
|
31
|
+
"examples/innate/Gemfile",
|
32
|
+
"examples/innate/README.rdoc",
|
33
|
+
"examples/innate/app.rb",
|
34
|
+
"examples/innate/start-with-raise.rb",
|
35
|
+
"examples/innate/start.rb",
|
36
|
+
"examples/innate/view/index.erb",
|
37
|
+
"examples/innate/view/notworking.erb",
|
38
|
+
"examples/innate/view/response.erb",
|
39
|
+
"examples/rack/Gemfile",
|
40
|
+
"examples/rack/README.rdoc",
|
41
|
+
"examples/rack/app.rb",
|
42
|
+
"examples/rack/config-with-raise.ru",
|
43
|
+
"examples/rack/config.ru",
|
44
|
+
"examples/sinatra/Gemfile",
|
45
|
+
"examples/sinatra/README.rdoc",
|
46
|
+
"examples/sinatra/app.rb",
|
47
|
+
"examples/sinatra/config-with-raise.ru",
|
48
|
+
"examples/sinatra/config.ru",
|
49
|
+
"examples/sinatra/views/form.erb",
|
50
|
+
"examples/sinatra/views/form_not_working.erb",
|
51
|
+
"examples/sinatra/views/response.erb",
|
52
|
+
"features/empty_responses.feature",
|
53
|
+
"features/raising_exception.feature",
|
54
|
+
"features/setup.feature",
|
55
|
+
"features/skip_some_routes.feature",
|
56
|
+
"features/step_definitions/request_steps.rb",
|
57
|
+
"features/step_definitions/response_steps.rb",
|
58
|
+
"features/step_definitions/setup_steps.rb",
|
59
|
+
"features/support/env.rb",
|
60
|
+
"features/support/fake_session.rb",
|
61
|
+
"features/variation_on_field_name.feature",
|
62
|
+
"features/variation_on_key_name.feature",
|
63
|
+
"lib/rack/csrf.rb",
|
64
|
+
"lib/rack/vendor/securerandom.rb",
|
65
|
+
"rack_csrf.gemspec",
|
66
|
+
"spec/csrf_spec.rb",
|
67
|
+
"spec/spec_helper.rb"
|
64
68
|
]
|
65
69
|
s.homepage = %q{http://github.com/baldowl/rack_csrf}
|
66
|
-
s.
|
70
|
+
s.licenses = ["MIT"]
|
71
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Csrf 2.2.0", "--main", "README.rdoc"]
|
67
72
|
s.require_paths = ["lib"]
|
68
73
|
s.rubyforge_project = %q{rackcsrf}
|
69
|
-
s.rubygems_version = %q{1.
|
74
|
+
s.rubygems_version = %q{1.7.2}
|
70
75
|
s.summary = %q{Anti-CSRF Rack middleware}
|
71
76
|
|
72
77
|
if s.respond_to? :specification_version then
|
73
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
74
78
|
s.specification_version = 3
|
75
79
|
|
76
80
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
data/spec/csrf_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
2
|
|
3
3
|
describe Rack::Csrf do
|
4
|
-
describe '
|
4
|
+
describe 'csrf_key' do
|
5
5
|
it "should be 'csrf.token' by default" do
|
6
6
|
Rack::Csrf.csrf_key.should == 'csrf.token'
|
7
7
|
end
|
@@ -13,7 +13,13 @@ describe Rack::Csrf do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe '
|
16
|
+
describe 'key' do
|
17
|
+
it 'should be the same as csrf_key' do
|
18
|
+
Rack::Csrf.method(:key).should == Rack::Csrf.method(:csrf_key)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'csrf_field' do
|
17
23
|
it "should be '_csrf' by default" do
|
18
24
|
Rack::Csrf.csrf_field.should == '_csrf'
|
19
25
|
end
|
@@ -25,7 +31,13 @@ describe Rack::Csrf do
|
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
28
|
-
describe '
|
34
|
+
describe 'field' do
|
35
|
+
it 'should be the same as csrf_field' do
|
36
|
+
Rack::Csrf.method(:field).should == Rack::Csrf.method(:csrf_field)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'csrf_token(env)' do
|
29
41
|
let(:env) { {'rack.session' => {}} }
|
30
42
|
|
31
43
|
specify {Rack::Csrf.csrf_token(env).should have_at_least(32).characters}
|
@@ -39,7 +51,6 @@ describe Rack::Csrf do
|
|
39
51
|
it 'should use the key provided by csrf_key' do
|
40
52
|
env['rack.session'].should be_empty
|
41
53
|
Rack::Csrf.csrf_token env
|
42
|
-
env['rack.session'].should_not be_empty
|
43
54
|
env['rack.session'][Rack::Csrf.csrf_key].should_not be_nil
|
44
55
|
end
|
45
56
|
end
|
@@ -48,8 +59,6 @@ describe Rack::Csrf do
|
|
48
59
|
it 'should store the token inside the session' do
|
49
60
|
env['rack.session'].should be_empty
|
50
61
|
csrf_token = Rack::Csrf.csrf_token(env)
|
51
|
-
env['rack.session'].should_not be_empty
|
52
|
-
env['rack.session'][Rack::Csrf.csrf_key].should_not be_nil
|
53
62
|
csrf_token.should == env['rack.session'][Rack::Csrf.csrf_key]
|
54
63
|
end
|
55
64
|
end
|
@@ -60,13 +69,18 @@ describe Rack::Csrf do
|
|
60
69
|
end
|
61
70
|
|
62
71
|
it 'should get the token from the session' do
|
63
|
-
env['rack.session'].should_not be_empty
|
64
72
|
env['rack.session'][Rack::Csrf.csrf_key].should == Rack::Csrf.csrf_token(env)
|
65
73
|
end
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
69
|
-
describe '
|
77
|
+
describe 'token(env)' do
|
78
|
+
it 'should be the same as csrf_token(env)' do
|
79
|
+
Rack::Csrf.method(:token).should == Rack::Csrf.method(:csrf_token)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'csrf_tag(env)' do
|
70
84
|
let(:env) { {'rack.session' => {}} }
|
71
85
|
|
72
86
|
let :tag do
|
@@ -92,4 +106,10 @@ describe Rack::Csrf do
|
|
92
106
|
tag.should =~ /#{quoted_value}/
|
93
107
|
end
|
94
108
|
end
|
109
|
+
|
110
|
+
describe 'tag(env)' do
|
111
|
+
it 'should be the same as csrf_tag(env)' do
|
112
|
+
Rack::Csrf.method(:tag).should == Rack::Csrf.method(:csrf_tag)
|
113
|
+
end
|
114
|
+
end
|
95
115
|
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:
|
5
|
-
prerelease:
|
4
|
+
hash: 7
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 2.
|
10
|
+
version: 2.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Emanuele Vicentini
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
19
|
-
default_executable:
|
18
|
+
date: 2011-04-12 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: rack
|
@@ -96,9 +95,11 @@ files:
|
|
96
95
|
- Rakefile
|
97
96
|
- VERSION
|
98
97
|
- cucumber.yml
|
98
|
+
- examples/camping/Gemfile
|
99
99
|
- examples/camping/README.rdoc
|
100
100
|
- examples/camping/app.rb
|
101
101
|
- examples/camping/config.ru
|
102
|
+
- examples/innate/Gemfile
|
102
103
|
- examples/innate/README.rdoc
|
103
104
|
- examples/innate/app.rb
|
104
105
|
- examples/innate/start-with-raise.rb
|
@@ -106,10 +107,12 @@ files:
|
|
106
107
|
- examples/innate/view/index.erb
|
107
108
|
- examples/innate/view/notworking.erb
|
108
109
|
- examples/innate/view/response.erb
|
110
|
+
- examples/rack/Gemfile
|
109
111
|
- examples/rack/README.rdoc
|
110
112
|
- examples/rack/app.rb
|
111
113
|
- examples/rack/config-with-raise.ru
|
112
114
|
- examples/rack/config.ru
|
115
|
+
- examples/sinatra/Gemfile
|
113
116
|
- examples/sinatra/README.rdoc
|
114
117
|
- examples/sinatra/app.rb
|
115
118
|
- examples/sinatra/config-with-raise.ru
|
@@ -133,17 +136,15 @@ files:
|
|
133
136
|
- rack_csrf.gemspec
|
134
137
|
- spec/csrf_spec.rb
|
135
138
|
- spec/spec_helper.rb
|
136
|
-
has_rdoc: true
|
137
139
|
homepage: http://github.com/baldowl/rack_csrf
|
138
|
-
licenses:
|
139
|
-
|
140
|
+
licenses:
|
141
|
+
- MIT
|
140
142
|
post_install_message:
|
141
143
|
rdoc_options:
|
142
|
-
- --charset=UTF-8
|
143
144
|
- --line-numbers
|
144
145
|
- --inline-source
|
145
146
|
- --title
|
146
|
-
- Rack::Csrf 2.
|
147
|
+
- Rack::Csrf 2.2.0
|
147
148
|
- --main
|
148
149
|
- README.rdoc
|
149
150
|
require_paths:
|
@@ -169,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
169
170
|
requirements: []
|
170
171
|
|
171
172
|
rubyforge_project: rackcsrf
|
172
|
-
rubygems_version: 1.
|
173
|
+
rubygems_version: 1.7.2
|
173
174
|
signing_key:
|
174
175
|
specification_version: 3
|
175
176
|
summary: Anti-CSRF Rack middleware
|