As the title reads, I can't get my session variables to be persistent over routes.
I call session_start() at the VERY beginning of my index.php.
Root route:
$app->get('/', function (Request $request, Response $response) {
$this->logger->addInfo("session id: " . $_SESSION['cus_id']);
$response = $this->view->render($response, "homepage.phtml", [
'test' => 'testing something',
'logged_in' => isset($_SESSION['cus_id'])
]);
return $response;
});
in my app.log I see that the session variable is non existent.
But this is my code after a successful login: (post to /login)
if ($customer !== false && password_verify($password, $customer['password'])) {
$_SESSION['cus_id'] = $customer['id'];
return $this->view->render($response, "homepage.phtml", [ 'logged_in' => true]);
}
I also used the logger here for testing purposes and it showed me that it saved the right id.
I have also used various extra libraries with the exact same result.
I also checked the official documentation, to no avail.
Question:
How do I get the session variables to be persistent throughout routes?
Or is the another way to save sessions? and or another way to solve this login problem?
I had the same problem after upgrading a server which resulted in a new server setting in the php.ini file.
For me, session.auto_start=1 in the php.ini did the trick.
Related
I need to show some values in all app, and sometimes I need to use these values between controllers.
I was trying to use Session, but I maybe it is not the answer to that, because if I am not wrong, Laravel store the session data temporarily in memory and only after everything has been executed, will it dump the session data into storage (file, cookie, redis, whatever).
So for example, I have a controller like that:
class GiftController extends Controller
{
public function dashboard(){
$token = (Session::has('token')) ? Session::get('token') : NULL;
if (is_null($token)){
return view('test.erro', ['message' => 'no session!']);
}else{
return view('test.ok', ['message' => $token]);
}
}
public function setsession(){
Session::put('token','xxxxxxxxxxxx');
return redirect('test/dashboard');
}
}
In this case, if I do an echo on Session::get('token') into the setsession(), is showing the value, but when it goes to the dashboard(), the session shows nothing.
What I am doing wrong?
or What is the better Idea to use instead off session?
I am using the Laravel Framework 5.8.37
I found the solution but I got it with the markskayff help.
He told me to Check my .env file, and he was right! It was a different SESSION_DRIVER value from config/session.php
In config/session.php was 'driver' => env ('SESSION_DRIVER', 'file')
Despite not having .env file but app.yaml since I am doing this project in GCP app engine, the session in this file was SESSION_DRIVER: cookie.
So I changed in config / session.php the line 'driver' => env ('SESSION_DRIVER', 'file') to 'driver' => env ('SESSION_DRIVER', 'cookie').
And now it is working!
I've been using the session in laravel to tie down unauthenticated users to quotes. But I'm running into an issue that I cannot get my head around and have a feeling it has something to do with the magic parts of Laravels back end.
Here is my code:
$session_id = session()->getId();
$booking = Booking::create([
'trip_start_date' => $request->pickup_date,
'trip_start_time' => $request->pickup_time,
'token' => $session_id,
'ip' => $request->ip(),
]);
session()->put('at_token', $session_id);
But then when validating the tokens in middleware, the tokens are completely different.. as logged in my file:
AT_TOKEN [pjIGjpuz0tRT0mjLTtdwgzTCDXrdwRCJssgJ1ukE]
BOOKING TOKEN [3fcjAzdKTOv2IGy3Zw7skh2c9PqN9O9G98BVbAO0]
I see the token in the session looks like a session ID but the one from the DB seems to be unlike a session ID... any help would be greatly appreciated.
EDIT: Middleware... Although this is clearly working, the tokens do not match but when storing the session ID to the session and the DB, I use the same variable so how can they not be the same?!
//user not logged in, check session
if (session()->has('at_token')) {
$token = session()->get('at_token');
if ($token == $booking->token) {
//user has the token, give them access
return $next($request);
}else{
Log::info("AT_TOKEN [$token] DOES NOT EQUAL THE BOOKING TOKEN [$booking->token]");
}
}else{
Log::info('NO AT_TOKEN');
}
The solution for your problem is here.
https://laravel.com/docs/5.6/middleware#registering-middleware
also here
https://laravel.com/docs/5.2/routing
The document states that by default the session is used inside middlewareGroups rather than middleware which is not assigned to the routes but rather assigned to web middleware. So the solution is to move the line
\Illuminate\Session\Middleware\StartSession::class,
to
protected $middleware = [
..........
\Illuminate\Session\Middleware\StartSession::class
........
]
Now your session will persist.
Environment
I created an application using Laravel 5.7 and implemented a REST API. I have a route in routes/api.php that triggers a middleware which checks if the incoming request has a parameter called api_token.
This is a production environment and here are the specifics:
Linux Ubuntu 18.04 LTS 64-bit
nginx/1.14.0
Laravel 5.7
PHP 7.2
APP_ENV in the .env file is set to 'production' and APP_DEBUG is set to 'false'.
Problem
My problem is that the incoming request object is always empty when it arrives at the server. At least that's what my Laravel application says.
These are my routes in routes/api.php:
Route::middleware('rest')->group(function() {
Route::get('device-location/{deviceID}', 'PositionDataController#getDeviceLocation');
Route::get('device-location/all', 'PositionDataController#getAllLocations');
Route::post('device-location', 'PositionDataController#storeDeviceLocation');
Route::put('device-location/{deviceID}', 'PositionDataController#updateDeviceLocation');
Route::delete('device-location/{deviceID}', 'PositionDataController#deleteDeviceLocation');
});
The routes are in a middleware group called 'rest' as you can see. I'm using the Route::get('device-location/{deviceID}', 'PositionDataController#getDeviceLocation'); route to test the functionality.
Here's the code from the middleware:
public function handle($request, Closure $next)
{
if(request()->all()) {
$deviceID = request()->device_id;
}
else {
return response()->json([
'error' => 'The request object is empty.',
'request' => request(),
'parameters' => request()->all(),
'content' => request()->getContent(),
'input' => request()->input()
], 500);
}
$device = MobileDevice::where('device_id', $deviceID)->first();
if($device) {
$deviceToken = $device->api_token;
if($deviceToken == request()->api_token) {
return $next($request);
}
else {
return response()->json(['error' => 'Token does not match.'], 500);
}
}
else {
return response()->json(['error' => 'The device with the id [' . $deviceID . '] could not be found.'], 500);
}
}
The middleware first checks if there are parameters in the request object and then does some logic to check if the right token was sent. If the request object is empty it returns some data to help me understand what went wrong.
I use Postman (https://www.getpostman.com) to test the API. Here's my Postman setup:
Postman setup
Postman headers
This is the response I get in Postman:
Postman response
I get the same result if I call that route in a browser.
Regardless of if I put in parameters or not the request seems to be always empty.
Here are the things that I've tried to do:
Not using the middleware
Using the $request variable instead of the helper request()
Switching between 'application/json' and 'application/x-www-form-urlencoded' in the Headers of my Postman setup
Calling that route in a browser
Updating to Laravel 5.7
The strange thing is that all of this works perfectly on my local environment and on a test server that has the same specs as the production server.
UPDATE 01:
So it seems to be even worse...
If I add a route like this in web.php:
Route::get('/request-return', function() {
return request()->all();
});
and visit that route like this:
laravel.application/request-return?device_id=1&api_token=XgkQLs8G7OYTqdwsXmjJT5G9bxv20DRi
I get back an empty array [].
So it seems like the parameters don't get to the server itself.
You are getting device id through GET request so use the below line instead of $request()->device_id.
Use this and let me know
$name = $request->input('device_id')
Okay I could solve the problem. It didn't have anything to do with Laravel. It was a nginx configuration problem:
https://serverfault.com/questions/231578/nginx-php-fpm-where-are-my-get-params
I'm accessing an api in my own project, but now I'm having problem with the route function, after dispatching the request with app()->handle($req), route function generate a different url
$req = Request::create('/api/auth/login', 'POST', [
"user" => $request->user,
"password" => $request->password,
]);
$redirect = route('home'); // http://127.0.0.1:8000/home
$res = app()->handle($req);
$redirect = route('home'); // http://localhost/home
What did I miss?
Request::create() is a method inherited from Symfony's HTTP Request class. When called, if you do not pass in any $_SERVER details, it will use reasonable defaults.
The UrlGenerator Laravel class uses the current Request to determine the fully-qualified domain name when calling functions such as route(). Since you did not tell the Request what the current domain is, it is reverting to localhost.
If you're in an environment where $_SERVER is populated with the proper information, you can pass it to the proper parameter:
Request::create(
'/api/auth/login',
'POST',
[
'user' => $request->user,
'password' => $request->password,
],
[], // cookies
[], // files
$_SERVER
);
Other potential solutions that may fit well:
Use Request::createFromGlobals() to populate a request with PHP's superglobals such as $_POST, $_SERVER, etc., then modify the parts that you want to change.
If the $request variable already holds a Laravel Request instance, you can call $request->duplicate(). And again, modify as needed.
I'm accessing an api in my own project, but now I'm having problem with the route function, after dispatching the request with app()->handle($req), route function generate a different url
$req = Request::create('/api/auth/login', 'POST', [
"user" => $request->user,
"password" => $request->password,
]);
$redirect = route('home'); // http://127.0.0.1:8000/home
$res = app()->handle($req);
$redirect = route('home'); // http://localhost/home
What did I miss?
Request::create() is a method inherited from Symfony's HTTP Request class. When called, if you do not pass in any $_SERVER details, it will use reasonable defaults.
The UrlGenerator Laravel class uses the current Request to determine the fully-qualified domain name when calling functions such as route(). Since you did not tell the Request what the current domain is, it is reverting to localhost.
If you're in an environment where $_SERVER is populated with the proper information, you can pass it to the proper parameter:
Request::create(
'/api/auth/login',
'POST',
[
'user' => $request->user,
'password' => $request->password,
],
[], // cookies
[], // files
$_SERVER
);
Other potential solutions that may fit well:
Use Request::createFromGlobals() to populate a request with PHP's superglobals such as $_POST, $_SERVER, etc., then modify the parts that you want to change.
If the $request variable already holds a Laravel Request instance, you can call $request->duplicate(). And again, modify as needed.