How is the 'cookie' global object supposed to work on xPages? It is a map, so I can check the cookie existence easily, but how to create a new cookie? Using cookie.name="value" raises an error because, as supposed, the cookie must be some object with params like expiration etc. But what kind of the object it is? I can't find any suitable documentation for this or I miss something.
cookie object represents a map of cookie values of the request instance. So you cannot use it because 'setting cookie' means 'adding cookie to the response'.
So, as the article suggests, you have to use response object.
var response = facesContext.getExternalContext().getResponse();
var userCookie = new javax.servlet.http.Cookie("name", "value");
userCookie.setMaxAge(60*60*24*365*10); // set age in seconds...
userCookie.setPath("/"); // cookie will be valid under this path
response.addCookie(userCookie);
I can not give an answer on the cookie global object, but the following article shows how to manage cookies in XPages using the javax.servlet.http.Cookie class:
http://www-10.lotus.com/ldd/ddwiki.nsf/dx/cookie-management.html
Maybe the cookie global object expects an object of type javax.servlet.http.Cookie?
Have you tried using resources and defining meta tag as Set-Cookie?
Related
I am trying to implement an authentication system and I've run into some problems and after a lot of troubleshooting I've come to realise that I don't fully understand the difference between theese three:
res.cookie(name, value, [options])
and
res.setHeader('Set-Cookie')
and
Cookies.set(name, value, [options]) //js-cookie npm package
I'm assuming that res.cookie (and res.setHeader) are coming from express.
Documentation for res.cookie states (just underneath the property table) that
All res.cookie() does is set the HTTP Set-Cookie header with the options provided. Any option not specified defaults to the value stated in RFC 6265.
So, res.cookie is just a wrapper around res.setHeader to make the code clearer: you can pass options as an object, instead of manually constructing a header value.
Both of those are called on a res (a.k.a response) object, so it's a serverside tool to tell the client "please put that into cookies".
As for the last one, Cookies.set, that is intended to be run on the client instead. Internally, it just sets the document.cookie propery.
So, if we build a tl;dr table of all mentioned cookie setting options, here they are:
function
side
needs manual formatting
res.cookie
server
no
res.setHeader
server
yes
Cookies.set
client
no
document.cookie =
client
yes
Introduction
So I am building a website with node.js, express, express-session, and sequelize.js. Once a user logs in, an instance of the Sequelize model User is created. In my route for user log-in (/auth/login), I have:
var user = (await User.findAll(
{where: {
username: username
}}))[0];
and I few lines down I assign that user to the session.
req.session.user = user;
And then I can persist any changes by simply calling the save method of req.session.user:
await req.session.user.save();
And indeed, if I add this line next:
console.log(Object.getPrototypeOf(req.session.user));
the output is [object SequelizeInstance:User]. So far so good.
Here is the problem
In another route (/users/myaccount/edit-bio) I am able to access the values of req.session.user. That is, the output of
console.log(req.session.user.username);
is seanletendre, as expected. But now when I call
await req.session.user.save();
all I get is the error message:
UnhandledPromiseRejectionWarning: TypeError: req.session.user.save is not a function
"That is weird," I thought, "isn't this the same object?" To investigate, I add the line:
console.log(Object.getPrototypeOf(req.session.user));
just as I did in the log-in route. And what is the output? It is: [object Object]. So it seems that somehow the prototype of req.session.user gets forgotten. I don't understand how this can be.
Is it possible to re-assign a prototype to a plain object?
Suspect A
Based on the comments to my question, I suspect that the prototype is lost when the session manager serializes req.session. It seems that, unlike I thought before,req.session does not point to the exact same session object for different requests. Each time a request ends, it serializes and stores req.session. Then upon receiving a new request with a cookie designating it as part of the same session, the session object is fetch from the session store.
This is how my session middleware is setup:
var session = require('express-session');
//
// yada, yada, yada
//
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {secure: true}
}));
So what surprises me is that, even though I am using the default store MemoryStore, my sessions are still serialized.
My question now becomes: how can I prevent object serialization upon session store when using MemoryStore?
In express-session the method save() is exposed by the object session into the request object (docs), eg.:
req.session.save(callback)
Your code req.session.user.save() is wrong, the correct way is req.session.save(), diff.:
req.session.user.save();
-----------^^^^^
req.session.save()
The method save() isn't a Promise, you must pass a callback for wait for the result of the save:
req.session.user = user;
req.session.save(function(err) {
if( err ){
// session not saved
} else {
// session saved
}
})
you can transform it into a Promise (and await it), in this way:
const saveSession = (req) => {
return new Promise((resolve, reject) => {
req.session.save(function(err) {
if( err ){
reject(err);
} else {
resolve(true);
}
});
});
};
req.session.user = user;
await saveSession(req);
The method save() is automatically called at the end of the HTTP response if the session data has been altered. Because of this, typically this method does not need to be called.
UPDATE
I call req.session.user.save() because I want to save the Sequelize
Model instance into my database.
express-session use JSON.stringify() for serialize the session into a string and store into a session storage (more info). JSON.stringify() doesn't understand functions and only property are stored. For this reason, your save() function is lost.
Is it possible to re-assign a prototype to a plain object?
Technically you could re-assign the .prototype and .constructor. However, a model instance is quite a complex object. Try logging it to debugging console and you'll see it has lots of sub-objects of its own kind and also references to other more distant objects residing in a "more global" space (nothing like the plain object after deserialization (of JSON basically)). You'd have to re-instanciate them all. That is very hard to do.
My question now becomes: how can I prevent object serialization upon session store when using MemoryStore?
I am not experienced with express-session, but from what i read i think it basically works with parsing and stringifying JSON. So you can't prevent it when using express-session.
What you could do:
Just store the user.id to req.session.user_id. And User.findOne({ where: { id }) upon reloading the session. You then get a "real" sequelize model instance. And that instance you could assign to req.user, so that it's available throughout the request.
If you also hoped to avoid reloading the user's instance upon every request, then you are searching for a "caching" solution, which is different from "sessions". You'd then use a caching system like memcache, redis or others. However, there too, you probably won't get back a "real" instance of the model from the caching server.
If you have only one server where your application is running on, you could have a global.users variable, where you store all user instances via their id. For example "global.users[12345] = user". Like with 1. you'd retrieve it (or when not found initially load it) based on session.user_id
Some more thoughts: In your place, i'd also invest some time in figuring out, if sequelize allows to populate a new User() instance with data from JSON, and tricking sequelize into believing that this is not a new record.
Also, keep in mind, that depending on your application, the user's data in the database can change, while in your session or global.users you miss these changes.
When using ctx.cookies.set(), KOA adds a 'set-cookie' header to the response. However, ctx.cookies.get() retains the cookie (if any) from the original request. This seems counter-intuitive if I'm overwriting it. Is there not a way to have the getter reflect the new value immediately, in the same request?
h = uuidv4();
console.log('set new cookie',h);
ctx.cookies.set('uuid',h,{httpOnly:false,overwrite:true});
//This outputs undefined or the value that came with the request,
//not the newly assigned value:
console.log('cookie is',ctx.cookies.get('uuid'));
I'm fairly new to node.js. What I'm looking for is something like PHP's $_SESSION[], in which values are updated and available immediately as well as being written to the response cookie. I understand I could pile the new uuid into ctx.state, but it seems cleaner to just be able to access ctx.cookies.get() anywhere further down the middleware chain and have access to what I just set it to.
Having a set() that doesn't change the result of its get() seems like code smell to me. Am I missing something?
Using node.js with Express. This question also pertains to Connect since that's the Express sub-component in question.
I receive a signed cookie from the client over socket.io. Then I take the value of it which is in this format:
s:sessionID.signature
Currently to validate this I had to manually require the cookie-signature module and use its unsign method, which requires me to .slice(2) the s: off of this string, and just feels kludgy.
Is there a convenience method for this? I feel like I ought to be able to just do something like:
mySessionID = express.unsignCookie(thisCookie, forThisSessionIDKey, withThisSecret);
But no such method exists... am I missing something?
Oh, BTW, I can't access res/req due to being in socket.io... Which is why I'm having to pass the session ID over from the client's cookie in the first place...
Here was the solution I ultimately found. Inside socket.js:
var parseSignedCookie = connect.utils.parseSignedCookie;
...
socket.on('taste:cookie', function (data, callback) {
var sid = data.sid;
sid = parseSignedCookie(sid['connect.sid'], "mySecret");
In express you call var app = module.exports = express.createServer(); which creates a new HTTPServer object. I'd like to get access to the current req object from this app(HTTPServer) object. Is there a way to do this?
The req object is only created when the underlying HTTPServer actually gets a request, and only lasts for as long as the request is processed. So it's not really meaningful to talk about it outside the context of a callback.
During a callback, you can simply copy the appropriate data from the session object somewhere else and use that copy in your websockets code. But you can't count on the request object, or even the session object, remaining after you've finished processing the request.
Showing a small code example would be helpful; it sounds like you've got an "XY problem" (you want to accomplish a goal X and you've decided that technique Y is the right way to do it, when in fact technique Z might work better).