Asked  7 Months ago    Answers:  5   Viewed   33 times

Here's config/session.php:

return [
    'driver' => 'file',
    'files' => storage_path().'/framework/sessions',
];

My storage/framework/sessions have 755 permissions.

When I put these 2 line in my controller

Session::set('aa', 'bb');
dd(Session::get('aa'));

I receive expected "bb" output. But if I comment first line:

// Session::set('aa', 'bb');
dd(Session::get('aa'));

and refresh page, I still expecting "bb" but getting null.

Also, storage/framework/sessions is empty.

What should I do to make Session working?

 Answers

94

Laravel 5 handles sessions via a middleware class called StartSession. More importantly, this middleware is a TerminableMiddleware and the code that actually saves the data (in your case to the session file) is located in the terminate method, which is run at the end of the request lifecycle:

public function terminate($request, $response)
{
    if ($this->sessionHandled && $this->sessionConfigured() && ! $this->usingCookieSessions())
    {
        $this->manager->driver()->save();
    }
}

When calling dd(Session::get('aa')); the request is being interrupted before the terminate method of the middleware can be called.

Funnily enough, the Laravel Middleware Documentation actually explains Terminable Middleware logic by giving the Laravel StartSession middleware as an example:

For example, the "session" middleware included with Laravel writes the session data to storage after the response has been sent to the browser.

That being said, try using var_dump() instead of using dd().

Wednesday, March 31, 2021
 
SuperString
answered 7 Months ago
37

The problem is because you are killing the script before Laravel finishes its application lifecycle, so the values put in session (but not yet stored) got killed too.

When a Laravel application lifecycle starts, any value put in Session are not yet stored until the application lifecycle ends. That is when any value put in Session will be finally/really stored.

If you check the source you will find the same aforementioned behavior:

 public function put($key, $value)
 {
     $all = $this->all();

     array_set($all, $key, $value);

     $this->replace($all);
 }

If you want to test it, do the following:

  1. Store a value in session without killing the script.

    Route::get('test', function() {
        Session::put('progress', '5%');
        // dd(Session::get('progress'));
    });
    
  2. Retrieve the value already stored:

    Route::get('test', function() {
        // Session::put('progress', '5%');
        dd(Session::get('progress'));
    });
    
Wednesday, March 31, 2021
 
Sethunath
answered 7 Months ago
19

You are Flashing session data and creating a view instead of redirecting, meaning the message will Flash for this request and for the next one, showing twice.

If you want to show the message on the current request without redirecting, I would suggest providing the errors to your View::make instead of trying to Flash the messages. If you MUST Flash the message on the current request, then you will need to Session::forget('key') or Session::flush() after your view.

Saturday, May 29, 2021
 
Zach
answered 5 Months ago
73

Try wrapping your routes (inside app/Http/routes.php) in a Route::group() with the web middleware:

Route::group(['middleware' => ['web']], function () {
    // My Routes
});

An easy way to test this:

Route::group(['middleware' => 'web'], function () {
    Route::get('', function () {
        Session::set('test', 'testing');
    });

    Route::get('other', function () {
        dd(Session::get('test'));
    });
});

If you remove the web middleware, you'll receive null since the web middleware is responsible for starting the session.

Ensure you have the web middleware group inside your app/Http/Kernel.php:

protected $middlewareGroups = [
    'web' => [
        MiddlewareEncryptCookies::class,
        IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
        IlluminateSessionMiddlewareStartSession::class,
        IlluminateViewMiddlewareShareErrorsFromSession::class,
        MiddlewareVerifyCsrfToken::class,
    ],
];
Saturday, May 29, 2021
 
exxed
answered 5 Months ago
44

PHP Sessions use a cookie to keep track of the session. You visit the page mydomain.com and the browser sends cookies for that domain, but when the javascript makes requests to api.mydomain.com it doesn't include cookies because it's a cross domain request so the session can't be tracked.

Token authentication is stateless meaning there is no session to save to or retrieve from. All the information needed for the request must be included in the request. So you get the user information from the token.

On your login page you post the credentials and return a token. Your frontend will then attach the token to every subsequent request.

This example assumes you use JWTAuth, but the concept would work with any token service.

  public function login(Request $request){

    // This is all unnecessary. You're in Laravel, take advantage of the services Laravel provides. Use [Request](https://laravel.com/docs/5.1/requests#retrieving-input) instead.
    //$postdata = file_get_contents("php://input");
    //$request = json_decode($postdata);
    //$requestArray = array();
    //foreach($request as $key => $value){
    //  $requestArray[$key] = $value;
    //}

    // change email to username depending on what you use to authenticate
    $credentials = $request->only('username', 'password');
    $user = User::login($requestArray);
    if($user){
        $token = JWTAuth::fromUser(User::where('username', $credentials['username'])->first());
    } else {
        return response()->json(array('error' => 'invalid credentials')))

    // all good so return the token
    return response()->json(compact('token'));

  }

Once you have a token you can use the JWT middleware jwt.auth to protect any route. To get the user info from the token use JWTAuth::toUser()

public function getCurrentUser()
{
    return JWTAuth::toUser()->toJson();
}

Instead of making requests to get session data from the server, you should store that information on the client side.

Saturday, May 29, 2021
 
rlanvin
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :