How can I prevent cache override expiry time in redis - spring

I have a generic method called save with Redis template :
redisTemplate.expire(cacheType.name(), redisPropertyConfiguration.getTimeToLive(), TimeUnit.MINUTES);
every time I called this method expire of the Redis template override the expiration time, I wanna prevent the expiration time and put it if the expiration time end

That is expected because expire(K key, long timeout, TimeUnit unit) (wrapper of the EXPIRE Redis command) is documented as
Set time to live for given key.
You ask :
I wanna prevent the expiration time and put it if the expiration time end
You cannot prevent expiration if you check the key after the expiration time.
What you can do is adding again the key in the case if that has expired.
In Redis, the command TTL fooKey returns the remaining time to live of the key.
And good news : the Spring Boot Redis Template API also implements that :
public Long getExpire(K key)
Get the time to live for key in seconds.
So you could write something like that :
if (redisTemplate.getExpire(cacheType.name()) == -1L){
// re-add the key-value
redisTemplate.opsForValue.set(cacheType.name(), fooValue);
}

Related

Spring Boot #Cachable - how to find out expire datetime at runtime?

When using #Cachable in Spring, is there any way to find out at runtime if the next method call would be a cache hit or cache miss? Or, at what datetime the cache expires?
The background is, it would be nice to have a scheduled job which refreshes caches just before they expire. Also, this could allow us to find out if caches are expired and show the user a message that the system is now refreshing the caches. "please hold on, we are refreshing your caches for XY" to let the user know what's going on. - Please note we use the Cacheable feature to cache method calls which collect data from multiple calls to a 3rd party system which take up to several minutes.
There is no such thing in the Spring Cache abstraction.
As the data collection takes minutes, and the users might need that last value while data is being collected, you can't wait for the cache eviction to collect new data.
One solution would be to add an #Scheduled task that populates the cache calling a method with the #CachePut.
CachedService.java
#CachePut(cacheNames="book", key="#isbn")
public Book updateBook(int id, Book book) {
// Left blank
}
Config.java
#Scheduled(fixedRate = 60000)
public void reportCurrentTime() {
log.info("refreshing cache");
... long data collection ...
// Call method that has #CachePut
service.updateBook(bookId, book);
log.info("cache refreshed");
}
The example shows 60000ms (1 minute), it updates the cache every minute. You have to calculate it so it is less time than the Spring Cache expiration time. i.e. (expire time - request time)

Nancy authentication session timeout

I am using Nancy.Authentication.Forms. The users are vociferously complaining that their sessions are timing out too quickly (less than 5 minutes). I've searched high and low but cannot find how to set the session timeout time to one hour. Any help is greatly appreciated.
Thanks,
Ross
I'm not 100% sure what could be causing it because of the little information provided. But I think your problem is probably due to the encryption/decryption of the cookie.
Cookie Encryption differs on application startup
By default, a new key is created every time you start the application, which would cause decryption of the cookie to fail, causing authentication to fail, and requiring you to re-authenticate to create a new cookie.
By setting your own keys, every after restart the decryption will always be the same. This is VERY important if you have a load balancer.
https://github.com/NancyFx/Nancy/wiki/Forms-Authentication#a-word-on-cryptography
Since I also did not find an answer, I would like to post my research result:
WithCookie accepts an expiration DateTime.
https://github.com/NancyFx/Nancy/blob/a9989a68db1c822d897932b2af5689284fe2ceb8/src/Nancy/ResponseExtensions.cs
public static Response WithCookie(this Response response, string name, string value, DateTime? expires);
In my case it would be:
return Response.AsRedirect(redirectUrl)
.WithCookie(SecurityExtensions.CookieName, newSession.Id.ToString(), DateTime.Now.AddHours(1));
For the session duration itself I didn't find anything yet.

Meteor Session Replacement?

In the latest Meteor release (version 0.5.8), Session has been removed from the server-side code.
Previously I've used Session to store client-specific variables for the server; what is the replacement for this functionality?
Example case: User One opens a browser, User Two opens a browser. One calls a method on the server setting some token, the other calls a method on the server doing the same. I then need to access this when the client requests something. How do I differentiate between the two?
You'll want to save your tokens to a collection in the database.
You could use a Session on the server if you wanted to simply by copying the session package into your application's packages directory and changing its package.js to also load on the server. But a Session is an in-memory data structure, and so won't work if you have multiple server instances; and you wouldn't be able to restart the server without losing your user's tokens.
If you store your tokens in the database they'll persist across server restarts, and will work with a future version of Meteor which is able to scale an application by adding more server instances when needed.
If you need to expire your tokens (so that your collection doesn't grow without bound), you could add a "lastUsed" Date field to your token collection, and periodically remove tokens that haven't been used for longer than your chosen expiration period.
You can use each one's session id which is unique to the tab too. Not too sure how to get the current session id but it should be there somewhere (you can see it in Meteor.default_server.sessions, so there is still a way:
Client js
Meteor.call("test", Meteor.default_connection._lastSessionId, function(err,result) {
console.log(result);
});
Server side Js
Session = {
set : function(key, value, sessionid) {
console.log(Meteor.default_server.sessions[sessionid]);
if(!Meteor.default_server.sessions[sessionid].session_hash) Meteor.default_server.sessions[sessionid].session_hash = {};
Meteor.default_server.sessions[sessionid].session_hash.key = value;
},
get : function(key, sessionid) {
if(Meteor.default_server.sessions[sessionid].session_hash)
return Meteor.default_server.sessions[sessionid].session_hash.key;
},
equals: function(key, value, sessionid) {
return (this.get(key, sessionid) == value)
},
listAllSessionids: function() {
return _.pluck(Meteor.default_server.sessions, "id");
}
};
Meteor.methods({
test:function(sessionid) {
if(!Session.get("initial_load", sessionid)) Session.set("initial_load", new Date().getTime(), sessionid);
return Session.get("initial_load", sessionid);
}
});
I hook into Meteor.default_connection._sessions to store the values so that theres some type of garbage collection involved when the session isn't valid anymore (i.e the user has closed his tabs) to prevent memory being wasted. In livedata_server.js these old sessions get destroyed after 1 minute of no activity on the DDP wire (like the heartbeat).
Because the server can see everyone's session you can use the sessionid to access another user's session data. and listAllSessionids to give out an array of all the sessionids currently active.
Automatically set session like this.userId in a Method without using a param in a call
It looks like there is functionality for this this but its not fully hooked up. The session id would be stored in this.sessionData but its likely still unfinished. Its there to be called in method but theres nowhere that its being set yet (in livedata_connection.js & livedata_server.js)

How to set expiration time to session in the controller?

I need to set a session with expiration time of 5min in controller. How do i do it?
I need something like:
$this->container->get('session')->set('mysession', 'value', 'expiration');
in symfony2 way?
Thanks!
Assuming your session is already created, you can achive your goal with:
$this->container->get('session')->migrate($destroy = false, $lifetime = null);
$destroy: Whether to delete the old session or leave it to garbage collection.
$lifetime: Sets the cookie lifetime for the session cookie. A null value will leave the system settings unchanged, 0 sets the cookie to expire with browser session. Time is in seconds, and is not a Unix timestamp.
This feature is added recently. You can update to this commit or patch. From the code it seems you can set expiry time by following way,
$this->container->get('session')->getMetadataBag()->stampNew(300);
To control the time of the active session (and idle time too) you have to do it in the controller this way (extract from: session configuration in the official doc):
$session->start();
if (time() - $session->getMetadataBag()->getCreated() > $maxTime) {
$session->invalidate();
throw new SessionExpired(); // redirect to expired session page
}
When time reaches your $maxTime session is "closed". You can put this code in the backend of your app as a function to call from the different methods to control the time.

ASP.NET MVC3 Forms Authentication user logon session renew

I have an AJAX method to call on server to return ".ASPXAUTH" cookie expiration time.
It works properly when the auth cookie presents.
Besides I want to renew user logon session with another AJAX call. I have a blank method "RenewSession" which is just for to make a call to the server. Is there any way to do this using Forms Authentication?
The problem is in that when I make a request to server to my "RenewSession" method to renew the session Response.Cookies array is always containing 0 items. But actually when the ".ASPXAUTH" cookie expiration time gets to 0 it renews.
So can anyone explain is it a browsers' or ASP.NET/MVCs' behaviour?
Maybe I need sliding expiration to be set to "true"?
Or maybe in my renew method I should re-login the user and put a new cookie in the response?
Thank you!
FormsAuthentication expiration is really a matter of two parts:
the expiration of the authentication ticket
the expiration of the cookie containing the ticket
If you want to leave sliding expiration off, and renew the ticket manually, you need to renew the ticket and return a new authentication cookie to the browser.
The Response.Cookies array is empty unless you (or other code) add something to it. It's only meant for adding cookies that are new or whose contents/expiration/whatever have changed. An empty Response.Cookies only means that nothing has changed - the browser will keep the cookies it already has (until they expire) and still send them on the next request.
The standard way of modifying cookie contents or expiration is to take a cookie the browser sent (from Request.Cookies), modify it, and then add it to Response.Cookies.
Here's a bit of sample code for manually renewing the authentication cookie (disclamer: Test thoroughly and think):
// You could also get the ticket from
// Request.Cookies using FormsAuthentication.Decode
FormsIdentity identity = HttpContext.Current.User.Identity as FormsIdentity;
if (identity == null) return; // User isn't authenticated
// Renew the ticket - you could also create a new ticket manually
// (see * below for an example), if you want to get rid of ASP.NET's
// rather confusing renew-if-old policy:
FormsAuthenticationTicket ticket =
FormsAuthentication.RenewTicketIfOld(identity.Ticket);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
encryptedTicket
);
// Better keep this (see * below):
cookie.Secure = FormsAuthentication.RequireSSL;
cookie.HttpOnly = true;
// Isn't a security issue if this is set too long - the ticket contained
// within will still expire after the set time, and the server will timeout
// the auth session on the next request.
// But let's just keep cookie and ticket in sync:
cookie.Expire = ticket.Expiration;
// Add cookie to response to send the changes to the browser:
HttpContext.Current.Response.Cookies.Add(cookie);
Note that FormsAuthentication.RenewTicketIfOld() won't always renew the ticket. It will only renew if less than half of the expiration time is left. I.e., if your timeout in web.config is set to 20 minutes and RenewTicketIfOld is called 7 minutes after the ticket was created, the ticket won't be renewed, and there'll still be 13 minutes left. If it's called after e.g. 12 minutes, it will be renewed to 20 minutes.
The reason for this is because RenewTicketIfOld is used by slidingExpiration on every request and so would send back a new cookie on every request (to reset the expiration to [timeout] minutes). Only sending a new ticket cookie back when at least half the time has elapsed gets rid of a lot of cookie overhead - at the expense of being confusing to developers and end users.
*) On cookie.Secure, see Hanselman: Weird Timeouts - this simply makes sure that if RequireSSL is set in web.config, the cookie will honor that, which avoids many a debugging nightmare if you ever move the site to SSL.

Resources