I'm having a problem associating a browser_id to a session when using Products.BeakerSessionDataManager. I'm working on Plone 5.
As far as I understand Zope sessions, as soon as .getSessionData() is called on a session data manager, a session data container is created if it did not exist. Furthermore, this data will contain a token, which is the same as the browser_id associated with the browser making the request. And finally, a cookie is set on the response with the name _ZopeId (and the value is the same as the token). Thus, when I use the default session data manager that come with Zope, I get this:
ipdb> context.session_data_manager.getSessionData()
id: 14737473151418102847, token: 38878600A7nh90DE9ao, content keys: []
However, when I use Products.BeakerSessionDataManager, the same call gives me this:
ipdb> context.session_data_manager.getSessionData()
{'_accessed_time': 1473745441.437582, '_creation_time': 1473745441.437582}
Moreover, no cookie is set.
Perusing some old Zope docs, I found a reference to getContainerKey(), so I thought that might get me the browser_id. However, the returned value is different on every request, so that does not work. Also, calling .getBrowserIdManager().getBrowserId() on the session_data_manager throws an error, because Beaker does not support browser id managers.
I want to set a cookie, and I want a token. I'm doing this so that I can identify anonymous clients in a voting application, so that they will not cast multiple votes (at least not in the same session - there are other mechanisms to allow voting only when certain other conditions are met).
Am I misunderstanding the machinery, or am I missing something?
Related
If a user deletes his cookies for a Flask site, does that effectively end that session? If not, is there any possible way that Flask could determine who the user is without the user signing in, so that the server can connect that user with his previous session?
The answer seems to be "Yes, Flask can sometimes 'figure out who you are' (re-associate you with your previous session) even if you delete your cookie".
This is because your Flask-Login session ID is generated from a deterministic algorithm based solely on your IP address and user_agent string.
I learned all this from reading the SO question linked below and its answers:
Constant Flask Session IDs
I made the following observations:
For same IP addresses, but different browsers I get different SIDs - that's expected;
For different IPs & same browser I again have different SIDs - expected;
For same IP address with same browser I get same SID - also expected;
Now, point (3) is interesting because even if I delete the
corresponding cookie the SID remains constant! To some extent
even that might be understandable, but actually I was expecting the
SID to change between different cookies. But the only difference I
see is that
session.new is True
for the first request immediately after the deletion of the cookie.
An answer to the same question:
It looks like you're using the Flask-Login extension. Here's the code
that generates the id token:
def _create_identifier():
base = unicode("%s|%s" % (request.remote_addr,
request.headers.get("User-Agent")), 'utf8', errors='replace')
hsh = md5()
hsh.update(base.encode("utf8"))
return hsh.digest()
It's basically just md5(ip_address + user_agent).
Session is more like unique id posted to you browser and ... So most of the time, when you change session(not session id), you just modify backend part
I'm using JMeter 3.2 to create some performance tests.
I have a set up where a thread group has multiple threads (users) which perform multiple loops requesting a resource, form a server, every time.
Each of the threads go through an once only controller which retrieves a token from a server, which identifies the user, and is required on all subsequent requests. The token is different every time it is generated, I cannot store it in a data set (csv) as it would later be invalid.
I have a data set (.csv file) containing username and password of my test users.
So far so good.. Now the threads need to request a resource on the server requiring the token to be sent. It goes well the first time, but the second time it starts messing up. It seems like each iteration uses data from the next row in the dataset, but the token retrieved (from the once only controller) is not linked to row of data (username and password) used, so something like this happens:
thread1: data1/token1 - good
thread2: data2/token2 - good
Perhaps thread2 finishes first and starts the new iteration:
thread2: data1/token2 - error
thread1: data2/token1 - error
So my question is: how can I link the token retrieved to a row in data set (as a variable), so that the correct token will be sent every time that piece of data is used for a request?
Edit
I have an idea. Creating a Hashtable with some data, from the data set, as key and the token as value, but I have some issue. I've created the following code:
import java.util.Hashtable;
map = new Hashtable();
vars.putObject("map", map);
but it cast the following error:
java.util.Hashtable cannot be cast to java.lang.String
I finally figured it out, though it might not be the most optimal solution. What I did is to create a property (variables won't work), which is a JSONObject. In this I can store an id (for my data) and the token linked to it. I transform it to a string and store it in the property.
In a preprocessor to the http request requiring the token I retrieve the property and parses it back to a JSONObject and can look up the token using the id.
Is there a way to delete the value from session witch revel the go web framework?
I have a function for validate captcha for user input, and I set the value of captcha in session, and delete the captcha from session if there nothing to do for client after 1 minute. The code is like:
time.AfterFunc(time.Minute, func() {
delete(this.Session, CSecurityCode)
})
But I can still get the old value of captcha , why, and how to fix this?
Anybody who can help me?
The Session value is valid only while processing a client request. i.e. between the time you get the request and the time you respond to that request. Its contents are kept in a cookie on the client side and you'll get a new Session every time the client connects to your server. Thus if you keep it for later use (like the name of your AfterFunc suggests, triggered by a timer?), anything you do with it will be lost on the next client connection.
In order to achieve what you want to do, you'll need to add a "lastSeen" timestamp to the Session. When a request comes in, check Session["lastSeen"], and if it's older than 1 minute, then you can discard CSecurityCode from it.
We're writing a custom SessionSecurityTokenCache so that our FedAuth cookies are valid across a webfarm with IsReferenceMode = true. We are also trying to enable sliding sessions, but it opens up a few questions around token expiration:
In Global.asax, we are handling the SessionAuthenticationModule_SessionSecurityTokenReceived event to check the remaining time on the token and reissue it if it is due to expire (within 5 mins, for example). In here, when we check token.ValidTo, it does not equal the expiryTime of the TokenCacheItem that we retrieved from cache. Why? How is TokenCacheItem.Expires supposed to be used?
In the AddOrUpdate method you're required to override, there's an expiryTime parameter; what is the intended use of this? Also asked here.
I'm new to the Go language (Golang) and I'm writing a web-based application. I'd like to use session variables, like the kind in PHP (variables that are available from one page to the next and unique for a user session). Is there something like that in Go? If not, how would I go about implementing them myself? Or what alternatives methods are there?
You probably want to take a look at gorilla. It has session support as documented here.
Other than that or possibly one of the other web toolkits for go you would have to roll your own.
Possible solutions might be:
goroutine per user session to store session variables in memory.
store your variables in a session cookie.
use a database to store user session data.
I'll leave the implementation details of each of those to the reader.
Here's an alternative in case you just want session support without a complete web toolkit.
https://github.com/bpowers/seshcookie
Here's another alternative (disclosure: I'm the author):
https://github.com/icza/session
Quoting from its doc:
This package provides an easy-to-use, extensible and secure session implementation and management. Package documentation can be found and godoc.org:
https://godoc.org/github.com/icza/session
This is "just" an HTTP session implementation and management, you can use it as-is, or with any existing Go web toolkits and frameworks.
Overview
There are 3 key players in the package:
Session is the (HTTP) session interface. We can use it to store and retrieve constant and variable attributes from it.
Store is a session store interface which is responsible to store sessions and make them retrievable by their IDs at the server side.
Manager is a session manager interface which is responsible to acquire a Session from an (incoming) HTTP request, and to add a Session to an HTTP response to let the client know about the session. A Manager has a backing Store which is responsible to manage Session values at server side.
Players of this package are represented by interfaces, and various implementations are provided for all these players.
You are not bound by the provided implementations, feel free to provide your own implementations for any of the players.
Usage
Usage can't be simpler than this. To get the current session associated with the http.Request:
sess := session.Get(r)
if sess == nil {
// No session (yet)
} else {
// We have a session, use it
}
To create a new session (e.g. on a successful login) and add it to an http.ResponseWriter (to let the client know about the session):
sess := session.NewSession()
session.Add(sess, w)
Let's see a more advanced session creation: let's provide a constant attribute (for the lifetime of the session) and an initial, variable attribute:
sess := session.NewSessionOptions(&session.SessOptions{
CAttrs: map[string]interface{}{"UserName": userName},
Attrs: map[string]interface{}{"Count": 1},
})
And to access these attributes and change value of "Count":
userName := sess.CAttr("UserName")
count := sess.Attr("Count").(int) // Type assertion, you might wanna check if it succeeds
sess.SetAttr("Count", count+1) // Increment count
(Of course variable attributes can be added later on too with Session.SetAttr(), not just at session creation.)
To remove a session (e.g. on logout):
session.Remove(sess, w)
Check out the session demo application which shows all these in action.
Google App Engine support
The package provides support for Google App Engine (GAE) platform.
The documentation doesn't include it (due to the +build appengine build constraint), but here it is: gae_memcache_store.go
The implementation stores sessions in the Memcache and also saves sessions to the Datastore as a backup in case data would be removed from the Memcache. This behaviour is optional, Datastore can be disabled completely. You can also choose whether saving to Datastore happens synchronously (in the same goroutine) or asynchronously (in another goroutine), resulting in faster response times.
We can use NewMemcacheStore() and NewMemcacheStoreOptions() functions to create a session Store implementation which stores sessions in GAE's Memcache. Important to note that since accessing the Memcache relies on Appengine Context which is bound to an http.Request, the returned Store can only be used for the lifetime of a request! Note that the Store will automatically "flush" sessions accessed from it when the Store is closed, so it is very important to close the Store at the end of your request; this is usually done by closing the session manager to which you passed the store (preferably with the defer statement).
So in each request handling we have to create a new session manager using a new Store, and we can use the session manager to do session-related tasks, something like this:
ctx := appengine.NewContext(r)
sessmgr := session.NewCookieManager(session.NewMemcacheStore(ctx))
defer sessmgr.Close() // This will ensure changes made to the session are auto-saved
// in Memcache (and optionally in the Datastore).
sess := sessmgr.Get(r) // Get current session
if sess != nil {
// Session exists, do something with it.
ctx.Infof("Count: %v", sess.Attr("Count"))
} else {
// No session yet, let's create one and add it:
sess = session.NewSession()
sess.SetAttr("Count", 1)
sessmgr.Add(sess, w)
}
Expired sessions are not automatically removed from the Datastore. To remove expired sessions, the package provides a PurgeExpiredSessFromDSFunc() function which returns an http.HandlerFunc. It is recommended to register the returned handler function to a path which then can be defined as a cron job to be called periodically, e.g. in every 30 minutes or so (your choice). As cron handlers may run up to 10 minutes, the returned handler will stop at 8 minutes
to complete safely even if there are more expired, undeleted sessions. It can be registered like this:
http.HandleFunc("/demo/purge", session.PurgeExpiredSessFromDSFunc(""))
Check out the GAE session demo application which shows how it can be used.
cron.yaml file of the demo shows how a cron job can be defined to purge expired sessions.
Check out the GAE session demo application which shows how to use this in action.