Skip to content

Commit 1e42ee2

Browse files
committed
Add Rails 7.1 CSRF token support
1 parent 9836b37 commit 1e42ee2

File tree

1 file changed

+24
-37
lines changed

1 file changed

+24
-37
lines changed

src/main/ruby/jruby/rack/session_store.rb

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# See the file LICENSE.txt for details.
66
#++
77

8-
require 'rack/session/abstract/id' unless defined?(::Rack::Session::Abstract::ID)
8+
require 'rack/session/abstract/id' unless defined?(::Rack::Session::Abstract::Persisted)
99

1010
module JRuby::Rack
1111
module Session
@@ -28,7 +28,7 @@ def method_missing(method, *args, &block)
2828
end
2929

3030
# Rack based SessionStore implementation but compatible with (older) AbstractStore.
31-
class SessionStore < ::Rack::Session::Abstract::ID
31+
class SessionStore < ::Rack::Session::Abstract::Persisted
3232

3333
ENV_SERVLET_SESSION_KEY = 'java.servlet_session'.freeze
3434
RAILS_SESSION_KEY = "__current_rails_session".freeze
@@ -37,13 +37,6 @@ def initialize(app, options={})
3737
super(app, options.merge!(:cookie_only => false, :defer => true))
3838
end
3939

40-
def context(env, app = @app)
41-
req = make_request env
42-
prepare_session(req)
43-
status, headers, body = app.call(req.env)
44-
commit_session(req, status, headers, body)
45-
end
46-
4740
# (public) servlet specific methods :
4841

4942
def get_servlet_session(env, create = false)
@@ -69,7 +62,7 @@ def get_servlet_session(env, create = false)
6962
servlet_session
7063
end
7164

72-
private # Rack::Session::Abstract::ID overrides :
65+
private # Rack::Session::Abstract::Persisted overrides :
7366

7467
def session_class
7568
::JRuby::Rack::Session::SessionHash
@@ -83,6 +76,7 @@ def generate_sid(secure = @sid_secure)
8376
nil # dummy method - no session id generation with servlet API
8477
end
8578

79+
# Alternative to overriding find_session(req)
8680
def load_session(req) # session_id arg for get_session alias
8781
session_id, session = false, {}
8882
if servlet_session = get_servlet_session(req.env)
@@ -122,40 +116,33 @@ def loaded_session?(session)
122116
! session.is_a?(::JRuby::Rack::Session::SessionHash) || session.loaded?
123117
end
124118

125-
def commit_session(req, status, headers, body)
126-
session = req.env[::Rack::RACK_SESSION]
127-
options = req.env[::Rack::RACK_SESSION_OPTIONS]
128-
129-
if options[:drop] || options[:renew]
130-
destroy_session(req.env, options[:id], options)
131-
end
132-
133-
return [status, headers, body] if options[:drop] || options[:skip]
119+
# Mirror behaviour of Rails ActionDispatch::Session::AbstractStore#commit_session for Rails 7.1+ compatibility
120+
def commit_session(req, res)
121+
commit_csrf_token req
122+
super(req, res)
123+
end
134124

135-
if loaded_session?(session)
136-
session_id = session.respond_to?(:id=) ? session.id : options[:id]
137-
session_data = session.to_hash.delete_if { |_,v| v.nil? }
138-
unless set_session(req.env, session_id, session_data, options)
139-
req.env["rack.errors"].puts("WARNING #{self.class.name} failed to save session. Content dropped.")
140-
end
125+
def commit_csrf_token(req)
126+
csrf_token = req.env[::ActionController::RequestForgeryProtection::CSRF_TOKEN] if defined? ::ActionController::RequestForgeryProtection::CSRF_TOKEN
127+
if csrf_token
128+
req.session[:_csrf_token] = csrf_token
141129
end
142-
143-
[status, headers, body]
144130
end
145131

146-
def set_session(env, session_id, hash, options)
147-
if session_id.nil? && hash.empty?
148-
destroy_session(env)
132+
def write_session(req, session_id, session_hash, options)
133+
if session_id.nil? && session_hash.empty?
134+
delete_session(req)
149135
return true
150136
end
151-
if servlet_session = get_servlet_session(env, true)
137+
138+
if servlet_session = get_servlet_session(req.env, true)
152139
begin
153140
servlet_session.synchronized do
154141
keys = servlet_session.getAttributeNames
155-
keys.select { |key| ! hash.has_key?(key) }.each do |key|
142+
keys.select { |key| ! session_hash.has_key?(key) }.each do |key|
156143
servlet_session.removeAttribute(key)
157144
end
158-
hash.delete_if do |key,value|
145+
session_hash.delete_if do |key,value|
159146
if String === key
160147
case value
161148
when String, Numeric, true, false, nil
@@ -171,8 +158,8 @@ def set_session(env, session_id, hash, options)
171158
end
172159
end
173160
end
174-
if ! hash.empty?
175-
marshalled_string = Marshal.dump(hash)
161+
if ! session_hash.empty?
162+
marshalled_string = Marshal.dump(session_hash)
176163
marshalled_bytes = marshalled_string.to_java_bytes
177164
servlet_session.setAttribute(RAILS_SESSION_KEY, marshalled_bytes)
178165
elsif servlet_session.getAttribute(RAILS_SESSION_KEY)
@@ -188,9 +175,9 @@ def set_session(env, session_id, hash, options)
188175
end
189176
end
190177

191-
def destroy_session(env, session_id = nil, options = nil)
178+
def delete_session(req, session_id = nil, options = nil)
192179
# session_id and options arg defaults for destory alias
193-
(session = get_servlet_session(env)) && session.synchronized { session.invalidate }
180+
(session = get_servlet_session(req.env)) && session.synchronized { session.invalidate }
194181
rescue java.lang.IllegalStateException # if session already invalid
195182
nil
196183
end

0 commit comments

Comments
 (0)