yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.23k stars 6.91k forks source link

[Session] Doesn't work session in PostgreSQL #18326

Closed Myks92 closed 3 years ago

Myks92 commented 3 years ago

What steps will reproduce the problem?

Doesn't work session in PostgreSQL 12.2

What is the expected result?

Authorization via session DB

Quite a strange bug, because it is simple, but however my problem is not solved... I updated the framework to 2.0.38 and switched to php74. After updating the backend application that stores sessions in files is working. But the frontend application which stores sessions in the database, refuses. Can't figure out why ... Did even direct authentication:

php public function actionLogin()
{
    $user = User::findOne(261);
    Yii::$app->user->login($user,1000*60*60*24);

    if (!Yii::$app->user->isGuest) {
        return $this->redirect('index');
        ///return $this->redirect(Yii::$app->homeUrl);
    }
}
php public function actionIndex()
{
    var_dump(123);
    var_dump(Yii::$app->user->identity);
    die();

    return $this->actionLogin();
}

It gets to the page. This means that he will authorize it for 1 second. And in Index it already disappears after the request. In this case, sessions in the database are created and they are not expired.

Config for session component

'session' => [
    'class' => 'yii\web\DbSession',
    'timeout' => intval(@$params['sessionTimeout']) ?: 180 * 60, // 180 мин
    'sessionTable' => '{{%auth_session}}',
    'writeCallback' => function ($session) {
        $loginTime = null;
        if (!Yii::$app->user->isGuest) {
            $loginTime = Yii::$app->user->identity->getLastLogin();
        }
        return [
            'user_id' => Yii::$app->user->id ?: 0,
            'ip' => Yii::$app->request->userIP,
            'login_time' => $loginTime,
        ];
    }
], 

This file works. This commit breaks my functionality.

What do you get instead?

Logout in one second

Additional info

Q A
Yii version 2.0.38
PHP version 7.4
Operating system CentOS
Myks92 commented 3 years ago

This file works. This commit breaks my functionality.

samdark commented 3 years ago

What's the schema of your session table?

Myks92 commented 3 years ago
create table auth_session
(
    id         varchar(60)  default ''::character varying not null constraint auth_session_pk primary key,
    expire     integer      default 0,
    data       text         default ''::text,
    user_id    integer      default 0,
    login_time timestamp(0),
    ip         varchar(255) default ''::character varying
);
samdark commented 3 years ago

Aha. Seems the issue is likely about data structure. Here's current one:

https://github.com/yiisoft/yii2/blob/master/framework/web/migrations/schema-pgsql.sql

Myks92 commented 3 years ago

How to reproduce the error?

  1. Install Yii2 Advanced from documentation
  2. Select web server Nginx and setting configuration from documentation
  3. Install PostgreSQL 12.2 and PHP74
  4. run command in console: php yii migrate --migrationPath=/var/www/yii2-test/vendor/yiisoft/yii2/web/migrations
  5. config main.php:
    
    <?php

use yii\web\DbSession;

return [ 'aliases' => [ '@bower' => '@vendor/bower-asset', '@npm' => '@vendor/npm-asset', ], 'vendorPath' => dirname(dirname(DIR)) . '/vendor', 'components' => [ 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'session' => [ 'class' => DbSession::class, 'timeout' => 180 * 60, // 180 мин 'sessionTable' => '{{%session}}', ], ], ];

6. Login with exists user

```php
<?php
namespace frontend\controllers;

use frontend\models\ResendVerificationEmailForm;
use frontend\models\VerifyEmailForm;
use Yii;
use yii\base\InvalidArgumentException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\models\LoginForm;
use common\models\User;
use frontend\models\PasswordResetRequestForm;
use frontend\models\ResetPasswordForm;
use frontend\models\SignupForm;
use frontend\models\ContactForm;

/**
 * Site controller
 */
class SiteController extends Controller
{
    ...

    public function actionLogin()
    {
        var_dump(Yii::$app->user->identity);

        $identity = User::findOne(1);
        Yii::$app->user->login($identity);

        die();
    }

    ...
}

The first page update will return null, and the second should return the authorized user, but in my case it also returns null

samdark commented 3 years ago

Alright. It is highly likely it is a valid bug. We need to reproduce it now and it seems we have all the prerequisites.

Myks92 commented 3 years ago

Alright! How can I help?

samdark commented 3 years ago

Right now you can't. We need to allocate some time to do the actual test locally, do git bisect to find the commit in question etc.

alex-code commented 3 years ago

Can you show your User class.

Myks92 commented 3 years ago

I using User model from Yii advanced template.

samdark commented 3 years ago

@Myks92 I've tried it with instructions in https://github.com/yiisoft/yii2/issues/18326#issuecomment-708053477:

  1. Got advanced app template.
  2. Initialized it with dev environment.
  3. Pointed DB to a Postgres instance.
  4. Adjusted config to use DbSession.
  5. Applied migrations (both application and session table ones).
  6. ./yii serve --docroot frontend/web/.
  7. Opened frontend in the browser.
  8. Registered a user.
  9. Activated it.
  10. Logged in keeping "remember me" off.
  11. Got to other pages. Session is valid, application works well.

So overall I cannot reproduce the issue. It must be either something in your application or server config or extra options that you haven't provided.