gorilla/sessions persistent between server restarts? - session

I have a general question about sessions. I am not very seasoned when it comes to this subject. I've tried with:
NewRediStore (gopkg.in/boj/redistore.v1)
NewCookieStore
NewFileSystemStore
I was under the impression that sessions could last between server restarts, hence the need for a 'store'. While my golang backend is running, I am able to set new sessions and retrieve them for multiple users/browsers. No problems there.
When I restart my server, I notice that all session access results in session.IsNew == true.
In Redis, I can see all the session keys after the restart, and even verified that .Getting the session results in the right ID retrieved, but IsNew is still set.
I guess intuitively, this makes sense because there must be some map in memory that leads to the setting of IsNew but I would think that if there was any hit for the cookie key in the store, IsNew should not be set. Am I going crazy? Is there something easy that I am doing wrong? Is this a fundamental misunderstanding of how to use sessions?
Please let me know if I need to include code or additional details.

I would have had the same assumptions you did, and browsing the source, it looks like it should work as you described. You might try debugging and stepping through it, particularly the New method for the store you're using (e.g. FilesystemStore.New or RediStore.New). If that method successfully reads the cookie and finds the session in the store, it should set IsNew = false, according to the source.
Also note that just checking the session ID is not a good way of validating this behavior. If you look at the source, it decodes the session ID from the cookie, then tries to look that up in the backing store. If the lookup fails, then the session ID will match, but IsNew will be true and there won't be any values in the session. Make sure you're setting some value in the session and check for that instead of the session ID. The behavior is different for the CookieStore since it stores the session data in the cookie itself.

Related

Hidden authentication in some websites

I find that some websites have sort of authentication even though no user is logged in. Taking plunker for example, even a non-logged in user can freeze a snippet such that other users cannot modify; whereas the user himself could always modify the snippet even though he opens the link in another browser tab.
My current solution is adding a type field (ie, anonym and normal) in the user model. Then, each time there is no normal user logged in, I systematically generate a unique random ID, register and login as an anonym user. It works, but the shortcoming is there are lots of anonym users in my database.
Does anyone have a better solution? Is there any "standard" way to realize this kind of hidden authentication?
I think method you are looking for is called session id. When you save as anonymous user web app creates a session with a session id which is used to identify the user by link. For example on plnkr it'll be something like https://plnkr.co/edit/session_id?p=catalogue where session_id is some sort of hash.
To freeze the snippet the session id is written into cookies with the flag, saying, for example, that the state is frozen. If you freeze it in Chrome and open in a Chrome's private window or in Firefox on the same computer, you wouldn't be able to unfreeze it. It'll behave the same way as for other users which have no cookies. In fact using session hash for cookies, rather than any user identification is better for security reasons.
Now this approach in a sense isn't any better, than creating anonymous users - you still have to save session records into the database to be able to open session context by link. In fact, it might happen to be simpler in your case to do exactly what you did if user is assumed to be present in lots of use cases and places in the code.
In many cases, however, separation of session from user makes lots of sense as it simplifies keeping session state after login or registration. Say some web stores would empty your basket after you register, causing quite a bit of frustration, especially if you put several small items into it which you now have to find again and put back. Those don't have sessions or don't use them correctly on registration or login.
Otherwise, as I wrote it's pretty much the same and you have to deal with many anonymous sessions which pollute the database unless you have some sort of wise retention policy, depending on you use case. Say, for example, a web site similar to plnkr.co which is used to share code snippets, and post them on sites such as stackoverflow should better keep those sessions while there are users accessing those say at least once a year. So sessions should have access date and policy would be that it's older than 1 year.
Hope it helps.
I have done similar using Local Storage. It allows you to store data on the browser. A user can then open tabs, close browser completely and reopen etc and the data is still there. It would then appear to be saved for them but actually it's just stored on their browser.
This wouldn't allow others to see what they have done though, so not sure if this is quite what you're after.
I wrapped them in functions in case I chose to change them out later, something like this
StoreLocalVariable: function (key, value) {
localStorage.setItem(key, value);
},
GetLocalVariable: function (key) {
return localStorage.getItem(key);
},
Some info including compatibility
https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API

grails - how create new session for different browser tabs

I'm trying to create simple web-app using grails.
Now, I need create new session when user opens same page in different tabs to avoid displaying same data in all opened tabs.
is it possible to define that page was opened in new tab? if it possible how create new session in controller action?.
or maybe there is a way to get something like browser tab-id?
You seem to misunderstand how a session works and they are assigned.
A session is per browser (and domain/host).
So, even though you can create a new session in a controller action it won't help because that will become the session for all the tabs of the browser and the previous session(s) will be invalidated/abandoned.
There is no such thing as a browser tab id.
You'll need to address the root issue which is causing your data affinity to be based on a browser session. Make it based on something else. (Just a general suggestion since this isn't part of your questions and you haven't provided any details.)
Here is my thoughts on this.
What you are trying to accomplish may appear simple but you will need some mechanism to capture who each session be whether it be a spring security username or actual http session id and to then store with that what controller actions they have visited so far and to keep this consistently updated whilst checking it over and over again.
Something as simple as
[
['10001':[controller:'someController', 'someAction'],[controller:'someController1', 'someAction1'],
],
['10002':[controller:'someController', 'someAction'],[controller:'someController1', 'someAction1']
]
Where '10001' is your key of your map and is your session id then it contains a list of internal maps of places visited that you capture and try to work out if they been there already - basically the question here is....
Where is the AI to say if they have seen someAction1 they should see action2 and what happens when they seen action1 and action2 and so on an ever ending loop of and what next ?
Either way you could do all that as a session variable that contains a map like above - the issue you will hit will be concurrent map (where it gets updated and read at the same time).
So you will then need to look over and into using concurrent hashmaps to get around such issues.
Either way the problem with all of above is the consistent logic to figure out if they have seen all possible options then what next ?
I think you are far better off thinking of it from a different point of view as in base it on timestamp and move the query or whatever it is to randomly generate a different output based on that timestamp since that is always going to change regardless of the user

one session per user or one session in every users

I am curious about the value of PHPSESSID because, I created a simple login-type web app. When I try to login with different accounts, the value of the PHPSESSID is not changing. I got curious if it does okay or not. Because I tried to login in youtube with different account too. But their SID's differ on each user.
My question is:
1) Is what happening on my web app okay ?
2) Is yes, how can I make a session ids per account/user ?
3) If no, how can I fix it ?
I would really appreciate your suggestions.
It partly depends on exactly how you implemented "login." One way to do it is simply to change the user-identity (which, by definition, is part of the data that is stored in the session), while keeping the same session.
Another equally-valid way to do it is to first update the existing session (to show that the user, in that session, is now "logged off") (maybe...), and then to coin a completely new session-id, thus starting an entirely new session, in which you now "log on."
One advantage of the second approach ... and probably the reason why so many sites do it this way ... has to do with the possibility that the user might wish to open a new browser-window, and to log-in to the application a second time, intending to keep both logins alive at the same time. If the session-id token is part of the URL, or maybe is part of a hidden form or what-have-you, such that both session-id's can be retained independently, it becomes possible for the user to do what he has done without conflict. Two parallel sessions exist. In one, he is logged on as "joe," and in the second, he is logged on as "jeff." And so on. One set of browser-windows (somehow ...) carries the "jeff session" token; others carry the "joe session" token.
Fundamentally, a "session" is just a pool of server-side values, identified by the (PHPSESSID ...) token furnished each time by the client. Exactly how you choose to manage it, is at your discretion. It's a design-decision with no "correct" approach.

SQLAlchemy session: how to keep it alive?

I have a session object that gets passed around a whole lot and at some point the following lines of code are called (this is unavoidable):
import transaction
transaction.commit()
This renders the session unusable (by closing it I think).
My question is two part:
How do I check if a session is still alive and well?
Is there a quick way to revitalize a dead session?
For 2: The only way I currently know is to use sqlalchemy.orm.scoped_session, then call query(...)get(id) many times to recreate the necessary model instances but this seems pretty darn inefficient.
EDIT
Here's an example of the sequence of events that causes the error:
modelInstance = DBSession.query(ModelClass).first()
import transaction
transaction.commit()
modelInstance.some_relationship
And here is the error:
sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <CategoryNode at 0x7fdc4c4b3110> is not bound to a Session; lazy load operation of attribute 'children' cannot proceed
I don't really want to turn off lazy loading.
EDIT
DBSession.is_active seems to be no indication of whether or not the session is in fact alive and well in this case:
transaction.commit()
print(DBSession.is_active)
this prints True...
EDIT
This seemed too big for a comment so I'm putting it here.
zzzeek said:
"An expired object will automatically load new state from the database, via the Session, as soon as you access anything on it, so there's no need to tell the Session to do anything here."
So how do I get stuff committed in such a way that this will happen? calling transaction.commit is wrong, what's the correct way?
so the first thing to observe here is "import transaction" is a package called zope.transaction. this is a generic transaction that takes hold of any number of sub-tasks, of which the SQLAlchemy Session is one of them, via the zope.sqlalchemy extension.
What zope.sqlalchemy here is going to do is call the begin()/rollback()/commit() methods of the Session itself, in response to it's own management of the "transaction".
The Session itself works in such a way that it is almost always ready for use, even if its internal transaction has been committed. When this happens, the Session upon next use just keeps going, either starting a new transaction if it's in autocommit=False, or if autocommit=True it continues in "autocommit" mode. Basically it is auto-revitalizing.
The one time that the Session is not able to proceed is if a flush has failed, and the rollback() method has not been called, which, when in autocommit=False mode, the Session would like you do to explicitly when flush() fails. To see if the Session is in this specific state, the session.is_active property will return False in that case.
I'm not 100% sure what the implications are of continuing to use the Session when zope.transaction is in use. I think it depends on how you're using zope.transaction in the bigger scheme.
Which leads us where lots of these questions do, which is what are you really trying to do. Like, "recreate the necessary model instances" is not something the Session does, unless you are referring to existing instances which have been expired (their guts emptied out). An expired object will automatically load new state from the database, via the Session, as soon as you access anything on it, so there's no need to tell the Session to do anything here.
It's of course an option to even turn off auto-expiration entirely, but that you are even arriving at a problem here implies something is not working as it should. Like there's some error message you're getting. More detail would be needed to understand exactly what the issue you're having is.

Remove session variable when user leaves page

I have a page that sets a session variable to hold a list of lookups from the database for the page when the page is loaded.
The page also will need to access that list of lookups when Ajax calls are made from the browser.
I'd like to not load the list of lookups from the database for each Ajax call, but I would like to remove the list of lookups from the session if the user leaves the page. Is there a best practice or recommended strategy for doing this?
You can clear the session variable with javascript using something like this
window.onbeforeunload = cleanup;
function cleanup()
{
// Clear session variable here
}
However, this isn't foolproof since the user could always disable javascript, etc. Usually this won't be an issue since the session variable will have a timeout anyway. If you are really concerned, you should remove any current sessions on page load.
Another option, depending on your situation, is to use the Caching.Cache class to hold the values. When you insert the values into the cache, you can set them to expire after a TimeSpan, and just set it for pretty short, like 5 minutes or so.
Note that while sessions are per user, their is only one cache per server instance.

Resources