Stop Devise from clearing session

2019-01-09 00:55发布

It seems when a user logs out via standard Devise controllers, Devise destroys the entire session store, not just its own data. Is there any way to avoid this behavior? I have other irrelevant data that should be kept around.

session[:my_var] = "123"

Log out via devise...

puts session[:my_var]
# => nil

4条回答
走好不送
2楼-- · 2019-01-09 01:24

In the lasts versions of devise it is not necesary to override the sessions controller, instead you can just use:

config.sign_out_all_scopes = false

In the devise.rb file to get the desired behaviour.

查看更多
劫难
3楼-- · 2019-01-09 01:28

The destroy¹ method of SessionsController contains the following line:

signed_out = Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)

The sign_out_all_scopes² method calls warden.logout without any arguments, and the sign_out³ method calls warden.logout(scope).

The documentation of the logout⁴ method states:

# Logout everyone and clear the session
env['warden'].logout

# Logout the default user but leave the rest of the session alone
env['warden'].logout(:default)

Conclusion: sign_out should preserve the session when given a specific scope. However, I don't see any way to do that. sign_out_all_scopes is always called first, and will only return false if it couldn't log any user out.

I recommend either posting a feature request on their issue tracker or developing your own authentication solution. Rails now provides has_secure_password, and these days people seem to be going for the latter in order to avoid running into these problems.


¹ Devise::SessionsController#destroy

² Devise::Controllers::Helpers#sign_out_all_scopes

³ Devise::Controllers::Helpers#sign_out

Warden::Proxy#logout

查看更多
唯我独甜
4楼-- · 2019-01-09 01:31

In addition to Mattheus. The statement

signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))

is perhaps the best general log out statement, considering the possibility of being signed in with multiple roles. If, for you case, your user is just signed in as one role, and you want to preserve the rest of the session on signout, the easiest way is to do:

$ git clone git://github.com/plataformatec/devise.git
$ cd devise
$ git branch my_devise
$ git checkout my_devise

Open app/controllers/devise/sessions_controller.rb in your editor. In the method destroy, replace

signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))

with

signed_out = sign_out(resource_name)

Save and exit editor and do

$ git commit -am "remove only warden data from session on logout, preserve other data."

In the Gemfile of your project, describe the dependency to devise like

gem 'devise', :path => "[YOUR PATH]/devise", :branch => "my_devise"
查看更多
迷人小祖宗
5楼-- · 2019-01-09 01:43

You could just override Devise's SessionController, like I did to preserve a shopping cart:

sessions_controller.rb

class SessionsController < Devise::SessionsController

    def destroy
        order_id = session[:order_id] 
        super  
        session[:order_id] = order_id
    end

end

routes.rb

devise_for :users, :controllers => { :sessions => "sessions" }
查看更多
登录 后发表回答