Rails ActiveRecord store and new session

后端 未结 3 446
轻奢々
轻奢々 2021-01-12 05:49

I am new to Rails and experience a strange issue I don\'t understand. I use ActiveRecord as a session store and need to add session id as a property of JSON responses for al

相关标签:
3条回答
  • 2021-01-12 05:54

    Renewing is still important and you should not disable it

    Also the new session id is generated after the execution of the controller, therefore after you have a chance to set the response to be sent to the client.

    The solution is to manually trigger the renewing of the session id

    In your ApplicationController add the method:

    protected
    
      def commit_session_now!
        return unless session.options[:renew]
    
        object = session.options.instance_variable_get('@by')
        env = session.options.instance_variable_get('@env')
        session_id = object.send(:destroy_session, env, session.id || object.generate_sid, session.options)
    
        session_data = session.to_hash.delete_if { |k,v| v.nil? }
        object.send(:set_session, env, session_id, session_data, session.options)
    
        session.options[:renew] = false
        session.options[:id] = session_id
      end
    

    Then in your controller you just call this method before getting the session id for your response

    def my_action
      ...
      commit_session_now!
      render json: {session_id: session.id}, status: :ok
    end
    

    The code in commit_session_now! comes from Rack::Session::Abstract::ID#commit_session https://github.com/rack/rack/blob/master/lib/rack/session/abstract/id.rb#L327

    0 讨论(0)
  • 2021-01-12 06:11

    Without knowing the details of your application, my suggestion would be to use a before_filter in your ApplicationController:

    class ApplicationController < ActionController::Base
      before_filter :use_session_id
    
      protected
      def use_session_id
        # Do something with session.id 
        # This will get called before any rendering happens
      end
    end
    
    0 讨论(0)
  • 2021-01-12 06:15

    The problem I experienced was caused by default Warden configuration. It renewed session id, but somehow the new id was not accessible via session.id.

    The only way I found to stop this behavior was putting this code into config/initializers/devise.rb:

    Warden::Manager.after_set_user do |user,auth,opts|
      auth.env["rack.session.options"][:renew] = false
    end
    

    Probably this method is not really good for security reasons, but I have no other ideas in a week of searching and reading sources.

    0 讨论(0)
提交回复
热议问题