可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm going through Michael Hartl's Railstutorial and I am stuck on Exercise 9.6.2. I searched online and used this code in my Sessions Helper:
module SessionsHelper
def sign_in(user)
session[:user_id] = user.id
self.current_user = user
end
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def signed_in?
!current_user.nil?
end
def sign_out
session[:user_id] = nil
self.current_user = nil
end
end
I found it online from: http://www.nimweb.it/web-development/ruby-on-rails-web-development/ruby-on-rails-tutorial-exercise-9-6-2-rails-session/
However, the user is not logged out when the browser is closed. Does anyone else have a solution to this?
回答1:
EDIT:
Looking at the link you gave, they write:
We can also start the server (with “$ rails s”) and verify the
functioning of our brand new session without cookies (we should be
logged out every time we close the browser).
(emphasis added)
Therefore, their solution is to simply turn off cookies, which results in a new session being created with each visit. They are not really talking about removing old sessions on the server side of the equation.
My original answer is left below for historical value:
(apologies if this is too general, I'm assuming you're not seeing the bigger picture)
Fundamentally, the web uses a pull-based model - clients make requests to do things on the server.
You can not 'force' the client to close a session, since closing a session is an action that the client must request from the server (eg: by logging out).
Therefore, typically sessions have a time-out period that is checked regularly. Each session has a 'start time' stored in the database, and sessions that are too old are purged.
That said, there may be some way in javascript to detect a browser close event and make some best-effort attempt to close the session. But there is no guarantee - the user can always forcefully kill the browser process, leaving the server totally in the dark.
In short, you can't rely on the client to close a session. A timeout is probably your best option.
回答2:
I was stuck at the same exercise while going through the tutorial. If you happened to use Firefox and decided to save the tabs and then quit, the browser apparently will save all your session data when you re-start the browser. This means that the user information saved in the session cookie will also be restored, and hence the user appears to be logged in after the browser is closed. I don't think the other browsers (chrome for example) have the same kind of behavior though. So a quick test is to use another browser and see if your code would work. Hope this helps.
回答3:
First thing is to clear out which session store you're using to avoid "confusion".
I guess the exercise uses the default (cookie) store but than of course you might have changed that already to active record store (or any other store that keeps the data on the server).
Check your config/initializers/session_store.rb
file to find out the session store being used.
Assuming you did not change anything about the store it should be configured to :cookie_store
, in that case you do not need to worry about anything as client side cookies are used to store session data and these cookies by default expire after the browser is closed (they're so called "session" cookies, just to be clear session here does refer to the cookie being present until your browsing session persist - closing the browser deletes the session cookie).
Of course this does not call any of the server side code such as sign_out
or session.destroy
on browser exit, but as the cookie holds all the session data and is deleted by the browser you no longer can access it thus might consider the session destroyed ...
Now, with server side session storage this gets more complicated, as mentioned in the previous answer "You can not 'force' the client to close a session".
What most people do is destroy "expired" sessions by hand e.g. http://guides.rubyonrails.org/security.html#session-expiry. Sample rake task https://gist.github.com/kares/919069
回答4:
I'm reading this great tutorial right now and got to the same assignment some 30 minutes ago.
Jeremy Roman answered exactly the question in this thread. Though he didn't provide a step-by-step answer, the thing that he mentioned, allowed me to figure out the answer.
Now to be more specific... Considering what Jeremy mentioned about sessions being expired automatically after the browser is closed, unless there is a "Expires" attribute specified for the corresponding cookie, the solution is related to the following chunk of code:
app/helpers/session_helper.rb:
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user = user
end
As per the tutorial itself, the permanent
method above is setting the 'Expires' cookie attribute to 20.years.from_now
. So this means that your session will persist for 20 years, unless you log out explicitly or delete your cookie.
So in order to expire your session when the browser is closed, you just need to create your cookie without any expiration date, which boils down to simply omitting permanent
:
app/helpers/session_helper.rb:
def sign_in(user)
cookies.signed[:remember_token] = [user.id, user.salt]
self.current_user = user
end
Though there may be other valid solutions, which are not obvious for me yet (after all I just started learning Rails), this one looks very simple - you don't even need to write anything - just delete permanent
and there you go! :)
回答5:
I know this answer comes a little over four years late, but I ran into the same issue myself, and it's been asked multiple times in various forms on SO. The only correct answer I found was here.
The issue is not the design of the problem. Of course, it's expected that this exercise be completed with cookies turned on. Rather, the issue is in a browser setting: to "continue where you left off" or "open my windows and tabs from last time" when launching the browser. This setting keeps sessions alive across browser close, which is exactly the behavior we don't want.
This issue is now referenced as a footnote in the tutorial (Chapter 8, Note 2). The author says, in regards to this browser setting and its attendant never-ending sessions,
...of course Rails has no control over this behavior.