keeping laravel session variable till user logs out - session

I have a simple authentications for user,In UserController I have a fuction called postLogin().
public function postLogin()
{
if(Auth::user()->attempt($credentials))
{
return Redirect::intended('desk')->with('stream',"SomeData");;
}
}
with above code I am able to log in successfullt with the "SomeData" variable which I am retrieving it by
<?php
$class = Session::get('stream');
var_dump($class);
?>
First time when it goes to "/desk" url it dumps the value perfectly fine that is "SomeData" but once I refresh the page it resets the session and the value turns to null.
How do I keep this value till the user logs out.

From the laravel official documentation :
Flash Data
Sometimes you may wish to store items in the session only for the next
request. You may do so using the flash method. Data stored in the
session using this method will only be available during the subsequent
HTTP request, and then will be deleted. Flash data is primarily useful
for short-lived status messages:
$request->session()->flash('status', 'Task was successful!');
If you need to keep your flash data around for even more requests, you
may use the reflash method, which will keep all of the flash data
around for an additional request. If you only need to keep specific
flash data around, you may use the keep method:
$request->session()->reflash();
$request->session()->keep(['username', 'email']);

Related

Best way to optionally cache responses in Laravel?

I'm building a Laravel API and i was wondering what the best method is for optionally caching responses?
Assuming i have the following UserController in my API:
public function index()
{
return Cache::remember('users', '3600', function() {
return new UserCollection(User::all());
});
}
Now let's say in my app front-end that i want to force a refresh just in case there has been an update to the users within the past hour and i do not want to wait 1 hour for the cache to empty. How can i force a cache refresh and query the users from the database rather than the cache without waiting for the cache to expire?
One thought i had was to pass an additional header and use Middleware to retrieve the uncached resource but i'm not sure on this idea.
Is there a better way of doing this?
Thanks

Only one User using entire web application at a time - Spring boot

In spring boot application only one user should be using the certain page at a time (let's call it home.jsp). Another users should be redirected to different page(let's call it another_home.jsp) if they appear when accessing that same url. User doesn't login and just uses the application as it is. Any policy can be used for home.jsp could be first-come-first-serve or any other.
If more than one users are using application at a time only one user should be using home.html and all rest of the others should be using another_home.jsp.
As no login is needed in the application I believe I need anonymous sessions. Also, session needs to be expired after some time of inactivity. I've searched spring security but couldn't find anything.
I think that you don't even need spring security. Simple http session will work too. As far as I can see you just want to allocate the stream to one user and for that you need first user's session id which you can compare against whenever the requests come again. So store session id and expire after some timeout with some Time object or Date object.
In properties
server.servlet.session.timeout = 600 // 10 minutes
Something like this
private String currSessionId = null;
private Date lastDate = new Date();
private Integer TIMEOUT = 600000; // 10 minutes
public String loadHomePage(Model model) {
if(currSessionId!=null && new Date().getTime()- lastDate.getTime()>TIMEOUT){
currSessionId = null;
}
if(currSessionId==null){
currSessionId = session.getId();
lastDate = new Date();
return "home";
}else{
if(session.getId().equals(currSessionId)){
return "home";
}else{
return "another_home";
}
}
}
This is as simple as it gets when you don't have logged in users to manage and also don't need to remember previous state where user left off. Let me know if it helps.
You need to create a serverside state that is either empty or stores the identifier of the visitor that is currently claiming /home.jsp.
This could be a field on a singleton Bean, or an entity in the database.
It has to expire automatically, or it will prevent new visitors forever to make a claim.
As long as the state is empty, the first visitors identifier will be stored in this state.
And from that moment on, you will redirect all other visitors to another_home.jsp
So the Controllers Code would be something like this
if(visitorHoldsTheClaim()) {
return "home.jsp"
} else if (noClaimActive()) {
createClaimForVisitor();
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
Depending on your implementation, these methods will do different things.
I'd usually recommend against serverside session state (more about this in Roy Fieldings Dissertation),
but for your use case, you need a way to identify a visitor over many requests.
A session would certainly be a very simple way to achieve this.
You can at least minimize session usage by only creating one session at a time - the one for the visitor that holds the claim.
In this case you'd never have more than one open session, and the visitor that owns the session is the visitor that holds the claim.
So in this case, the implementation would be be something like this:
if(currentUserHasASession()) { // checks if the current user has a session, but !!!does not create a new session if it does not exist!!! careful, HttpServletRequest.getSession(true) would create it!
return "home.jsp"
} else if (serverHasNoSessions()) { // https://stackoverflow.com/questions/49539076/how-can-i-get-a-list-of-all-sessions-in-spring
createSessionForUser(); // HttpServletRequest.getSession(true)
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
Keep in mind that this only works if you do not create Sessions in another place.
So you have to configure Spring Boot/Spring Security to not create Sessions. How to make spring boot never issue session cookie?
Also keep concurrency in mind. For example, if you had only one server instance, you could put this code into a synchronized method to avoid two visitors creating a claim at the same time.
So... first of all, this sounds like a bad idea. I would be curious why you would need such an unusual behavior. There might be more sensible approaches for it.
Like Gregor said, the redirect code part is rather straightforward:
if(pageLock.getUser() == null) {
pageLock.setUser(user);
}
if(user.equals(pageLock.getUser())) {
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
What is actually more tricky is the part when "expiring" the lock. It's likely the user will simply close the browser and not click on "logout" (or whatever), leaving the lock forever. On the other extreme, the user might be gone for a lunch break but its browser still has the page open for hours.
So that's the first thing you wanna add: some keep-alive mechanism on the page, regularly prolonging the lock, and some expiration checker, releasing the lock if nothing was received for a while.
...but like I said in the beginning, the whole thing sounds fishy.

Trigger function after session timeout or expire in laravel

Hello i'm kinda new to laravel and i have a question concerning authentication. I have the following function in my authentication controller:
public function signout()
{
// set logged in status to zero in database
$l = Login::where('user_id', Session::get('user')->user_id)
->where('logged_in', 1)->first();
$l->logged_in = 0;
if ($l->save())
{
// log user out
Auth::logout();
// Forget user session data
Session::forget('user');
// redirect user to login page
return Redirect::to('/account/signin');
}
}
Now in my session config, i have set sessions to expire after 60mins after which the user will obviously be logged out of the system. However that will occur without my other functions executing like setting user logged in status to zero in database or forgetting the user session array. Is there a way i can trigger those functions to execute after login session expire? Thank you in advance.
Update: I've been looking around again ever since i got a down vote for my question to see if there was already a solution to this, from reading the docs i got excited when i came to the "Events" section because i thought i had found a solution however i found out later on that there was no such thing as a "Session::expire" event in laravel, neither is there a function to check whether another user is logged in or not.
Your whole premise is wrong: sessions should have an expiry timestamp that's set when user logs in, and updated on every request if you want to have something like "session times out after 1h of inactivity".
Then you can basically:
Check if session is still valid when user performs a request, by checking the timestamp
Delete expired sessions using a scheduled task, so you keep things clean and tidy in the background
Anyway, if for some reason you end up needing to trigger some actions to happen when a user signs out Laravel actually has an Event that's triggered on user logout: 'auth.logout'

Laravel IoC and singleton pattern

I'm trying to use Laravel IoC by creating a singleton object. I'm following the pattern from tutorial as below. I have put a Log message into object (Foobar in this example) constructor and I can see that object is being created every time I refresh page in browser. How is the singleton pattern meant for Laravels IoC? I understood that its shared object for entire application but its obviously being created every time its requested by App:make(...) Can someone explain please. I thought I would use the singleton pattern for maintaining shared MongoDB connection.
App::singleton('foo', function()
{
return new FooBar;
});
What has been said in Laravel Doc
Sometimes, you may wish to bind something into the container that
should only be resolved once, and the same instance should be returned
on subsequent calls into the container:
This is how you can bind a singleton object and you did it right
App::singleton('foo', function()
{
return new FooBar;
});
But, the problem is, you are thinking about the whole process of the request and response in the wrong way. You mentioned that,
I can see that object is being created every time I refresh page in
browser.
Well, this is normal behaviour of HTTP request because every time you are refreshing the page means every time you are sending a new request and every time the application is booting up and processing the request you've sent and finally, once the application sends the response in your browser, it's job is finished, nothing is kept (session, cookie are persistent and different in this case) in the server.
Now, it has been said that the same instance should be returned on subsequent calls, in this case, the subsequent calls mean that, if you call App::make(...) several times on the same request, in the single life cycle of the application then it won't make new instances every time. For example, if you call twice, something like this
App::before(function($request)
{
App::singleton('myApp', function(){ ... });
});
In the same request, in your controller, you call at first
class HomeController {
public function showWelcome()
{
App::make('myApp'); // new instance will be returned
// ...
}
}
And again you call it in after filter second time
App::after(function($request, $response)
{
App::make('myApp'); // Application will check for an instance and if found, it'll be returned
});
In this case, both calls happened in the same request and because of being a singleton, the container makes only one instance at the first call and keeps the instance to use it later and returns the same instance on subsequent calls.
It is meant to be used multiple times throughout the applications instance. Each time you refresh the page, it's a new instance of the application.
Check this out for more info and practical usage: http://codehappy.daylerees.com/ioc-container
It's written for L3, but the same applies for L4.

How to Track the Online Status of Users of my WebSite?

I want to track users that are online at the moment.
The definition of being online is when they are on the index page of the website which
has the chat function.
So far, all I can think of is setting a cookie for the user and, when the cookie is found on the next visit, an ajax call is made to update a table with their username, their status online and the time.
Now my actual question is, how can I reliably turn their status to off when they leave
the website? The only thing I can think of is to set a predetermined amount of time of no user interaction and then set the status to off.
But what I really want is to keep the status on as long as they are on the site, with or without interaction, and only go to off when they leave the site.
Full Solution. Start-to-finish.
If you only want this working on the index.php page, you could send updates to the server asynchronously (AJAX-style) alerting the server that $_SESSION["userid"] is still online.
setInterval("update()", 10000); // Update every 10 seconds
function update() {
$.post("update.php"); // Sends request to update.php
}
Your update.php file would have a bit of code like this:
session_start();
if ($_SESSION["userid"])
updateUserStatus($_SESSION["userid"]);
This all assumes that you store your userid as a session-variable when users login to your website. The updateUserStatus() function is just a simple query, like the following:
UPDATE users
SET lastActiveTime = NOW()
WHERE userid = $userid
So that takes care of your storage. Now to retrieve the list of users who are "online." For this, you'll want another jQuery-call, and another setInterval() call:
setInterval("getList()", 10000) // Get users-online every 10 seconds
function getList() {
$.post("getList.php", function(list) {
$("listBox").html(list);
});
}
This function requests a bit of HTML form the server every 10 seconds. The getList.php page would look like this:
session_start();
if (!$_SESSION["userid"])
die; // Don't give the list to anybody not logged in
$users = getOnlineUsers(); /* Gets all users with lastActiveTime within the
last 1 minute */
$output = "<ul>";
foreach ($users as $user) {
$output .= "<li>".$user["userName"]."</li>";
}
$output .= "</ul>";
print $output;
That would output the following HTML:
<ul>
<li>Jonathan Sampson</li>
<li>Paolo Bergantino</li>
<li>John Skeet</li>
</ul>
That list is included in your jQuery variable named "list." Look back up into our last jQuery block and you'll see it there.
jQuery will take this list, and place it within a div having the classname of "listBox."
<div class="listBox"></div>
Hope this gets you going.
In the general case, there's no way to know when a user leaves your page.
But you can do things behind the scenes such that they load something from your server frequently while they're on the page, eg. by loading an <iframe> with some content that reloads every minute:
<meta http-equiv="refresh" content="60">
That will cause some small extra server load, but it will do what you want (if not to the second).
Well, how does the chat function work? Is it an ajax-based chat system?
Ajax-based chat systems work by the clients consistently hitting the chat server to see if there are any new messages in queue. If this is the case, you can update the user's online status either in a cookie or a PHP Session (assuming you are using PHP, of course). Then you can set the online timeout to be something slightly longer than the update frequency.
That is, if your chat system typically requests new messages from the server every 5 seconds, then you can assume that any user who hasn't sent a request for 10-15 seconds is no longer on the chat page.
If you are not using an ajax-based chat system (maybe Java or something), then you can still accomplish the same thing by adding an ajax request that goes out to the server periodically to establish whether or not the user is online.
I would not suggest storing this online status information in a database. Querying the database every couple of seconds to see who is online and who isn't is very resource intensive, especially if this is a large site. You should cache this information and operate on the cache (very fast) vs. the database (very slow by comparison).
The question is tagged as "jquery" - what about a javascript solution? Instead of meta/refresh you could use window.setInterval(), perform an ajax-request and provide something "useful" like e.g. an updated "who's online" list (if you consider that useful ;-))
I have not tried this, so take it with a grain of salt: Set an event handler for window.onunload that notifies the server when the user leaves the page. Some problems with this are 1.) the event won't fire if the browser or computer crashes, and 2.) if the user has two instances of the index page open and closes one, they will appear to logout unless you implement reference counting. On its own this is not robust, but combined with Jonathan's polling method, should allow you to have pretty good response time and larger intervals between updates.
The ultimate solution would be implementing something with websockets.

Resources