繁体   English   中英

Yii2用SQLite数据库登录似乎不起作用

[英]Yii2 Login with SQLite database doesn't seem to work

我很沮丧。 已经从Google和SO中搜索了……

我正在使用基本的Yii2模板并尝试实现“用户登录”,但无法弄清楚为什么它无法登录。

问题是,我必须使用具有可怕结构的现有数据库:

| Category | Subcategory |    Name     |     Value     |
|    ...   |     ...     |    ...      |     ....      |
|     9    |   23712298  |   "Alias"   | "myUsername"  |
|     9    |   23712298  | "Password"  |   "test123"   |
|     9    |   15032862  |   "Alias"   | "myUsername2" |
|     9    |   15032862  | "Password"  |  "test12345"  |
|    ...   |     ...     |    ...      |     ....      |

如您所见, "Alias" =用户名和password是用户password的bcrypt哈希。

这是我的StudyController.php(摘录):

<?php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;
use app\models\Study;
use app\models\StudySearch;
use app\models\Image;
use app\models\User;
use app\models\LoginForm;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;

class StudyController extends Controller {
  public function behaviors() {
    return [
        'access' => [
            'class' => AccessControl::className(),
            'only' => ['index', 'show-images', 'logout'],
            'rules' => [
                [
                    'allow' => true, // allow rule
                    'actions' => ['login'], // empty array: deny/allow all
                    'roles' => ['?'], // not authorized / guest
                ],
                [
                    'allow' => true, // allow rule
                    'actions' => ['index', 'show-images', 'logout'],
                    'roles' => ['@'], // logged-in user
                ],
            ],
        ],
        'verbs' => [
            'class' => VerbFilter::className(),
            'actions' => [
                'logout' => ['post'],
            ],
        ],
    ];
  }

public function actionLogin()
{
    if (!\Yii::$app->user->isGuest) {
        return $this->goHome();
        //return $this->redirect('/study/index');
    }

    $model = new LoginForm();
    if ($model->load(Yii::$app->request->post()) && $model->login()) {
        return $this->goHome();
        //return $this->goBack();
    }

    return $this->render('login', [
        'model' => $model,
    ]);
}

这是我的LoginForm.php模型:

<?php

namespace app\models;

use Yii;
use yii\base\Model;
use app\models\User;

class LoginForm extends Model
{
    public $username;
    public $password;
    public $rememberMe = true;

    private $_user = false;


    /**
     * @return array the validation rules.
     */
    public function rules()
    {
        return [
            // username and password are both required
            [['username', 'password'], 'required'],
            // rememberMe must be a boolean value
            ['rememberMe', 'boolean'],
            // password is validated by validatePassword()
            ['password', 'validatePassword'],
        ];
    }

    /**
     * Validates the password.
     * This method serves as the inline validation for password.
     *
     * @param string $attribute the attribute currently being validated
     * @param array $params the additional name-value pairs given in the rule
     */
    public function validatePassword($attribute, $params)
    {
        if (!$this->hasErrors()) {
            $user = $this->getUser();

            if (!$user || !$user->validatePassword($this->password)) {
                $this->addError($attribute, 'Incorrect username or password.');
            }
        }
    }

    /**
     * Logs in a user using the provided username and password.
     * @return boolean whether the user is logged in successfully
     */
    public function login()
    {
        if ($this->validate()) {
            return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
        }
        return false;
    }

    /**
     * Finds user by [[username]]
     *
     * @return User|null
     */
    public function getUser()
    {
        if ($this->_user === false) {
            $this->_user = User::findByUsername($this->username);
        }

        return $this->_user;
    }
}

和实现IdentityInterface的用户模型:

<?php

namespace app\models;

use Yii;
use yii\web\IdentityInterface;
use yii\base\NotSupportedException;

/**
 * This is the model class for table "Config".
 */
class User extends \yii\db\ActiveRecord implements IdentityInterface
{
    public static $userID;
    public static $hash;

    public $authKey;

    public static function tableName()
    {
        return 'Config';
    }

    public static function getDb()
    {
        return Yii::$app->dbConfig;
    }

    public function rules()
    {
        return [
            [['username', 'hash'], 'required'],
            [['username', 'hash'], 'string'],
        ];
    }

    public static function findIdentity($id) {
        $sql = 'SELECT DISTINCT a.Subcategory as id, a.Value as username, b.Value AS hash FROM Config as a, Config as b
                    WHERE
                        a.Category=b.Category AND a.Subcategory=b.Subcategory
                        AND a.Category = 9 AND a.Name = "Alias" and b.Name="Password" AND id = :id';

        $user = static::findBySql($sql, [':id' => $id])->one();
        if(!empty($user)) {
            self::$userID = $user->id;
            self::$hash = $user->hash;
        }

        return (!empty($user)) ? new static($user) : null;
    }

    public static function findByUsername($username) {
        $sql = 'SELECT DISTINCT a.Subcategory as id, a.Value as username, b.Value AS hash FROM Config as a, Config as b
                    WHERE
                        a.Category=b.Category AND a.Subcategory=b.Subcategory
                        AND a.Category = 9 AND a.Name = "Alias" and b.Name="Password" AND username = :username';

        $user = static::findBySql($sql, [':username' => $username])->one();

        if(!empty($user)) {
            self::$userID = $user->id;
            self::$hash = $user->hash;
        }

        return (!empty($user)) ? $user : null;
    }

    public static function validatePassword($password) {
        return Yii::$app->getSecurity()->validatePassword($password, self::$hash);
    }

    public function getId() {
        if(empty(self::$userID)) {
            throw new NotSupportedException('getID ist leer'); // just testing
        }
        else {
            return self::$userID;
        }
    }

    public function setId($id) {
        self::$userID = $id;
    }

    public function getHash() {
        return self::$hash;
    }

    public function setHash($hash) {
        self::$hash = $hash;
    }

    public static function findIdentityByAccessToken($token, $type = null) {
        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    } 
    public function getAuthKey() {
        //$this->generateAuthKey();
        return $this->authKey;
    }
    public function validateAuthKey($authKey) {
        return $this->getAuthKey() === $authKey;
    }

    public function generateAuthKey() {
        $this->authKey = \Yii::$app->getSecurity()->generateRandomString();
        $this->save();
    }

    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if ($this->isNewRecord) {
                //$this->authKey = \Yii::$app->getSecurity()->generateRandomString();
                $this->generateAuthKey();
            }
            return true;
        }
        return false;
    }
}

最后但并非最不重要的是,登录视图:

<?php

/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model app\models\LoginForm */

use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use app\models\User;

$this->title = 'Login';
$this->params['breadcrumbs'][] = $this->title;

echo '<pre>';
print_r(Yii::$app->request->post());
echo '</pre>';

echo '<pre>';
print_r(Yii::$app->user->identity);
echo '</pre>';
?>
<div class="site-login">
    <h1><?= Html::encode($this->title) ?></h1>

    <p>Please fill out the following fields to login:</p>

    <?php $form = ActiveForm::begin([
        'id' => 'login-form',
        'options' => ['class' => 'form-horizontal'],
        'fieldConfig' => [
            'template' => "{label}\n<div class=\"col-lg-3\">{input}</div>\n<div class=\"col-lg-8\">{error}</div>",
            'labelOptions' => ['class' => 'col-lg-1 control-label'],
        ],
    ]); ?>

        <?= $form->field($model, 'username') ?>

        <?= $form->field($model, 'password')->passwordInput() ?>

        <?= $form->field($model, 'rememberMe')->checkbox([
            'template' => "<div class=\"col-lg-offset-1 col-lg-3\">{input} {label}</div>\n<div class=\"col-lg-8\">{error}</div>",
        ]) ?>

        <div class="form-group">
            <div class="col-lg-offset-1 col-lg-11">
                <?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
            </div>
        </div>

    <?php ActiveForm::end(); ?>
</div>

当我打开登录表单并输入有效的用户名和密码时,它将带我回到登录表单。 查看Gii Logs,这是输出: Gii输出正如您所看到的,它显然已使我登录。仍然无法转到另一个子页面。

Cookie“ _identity”在那里,在User.php模型中我自己的数据库查询似乎可以正常工作(否则屏幕截图将不会显示正确的userID)。

这是我的配置的用户组件部分:

'components' => [
    'user' => [
        'identityClass' => 'app\models\User',   
        'enableAutoLogin' => true,
        'enableSession' => true,
        'loginUrl' => ['study/login'],
    ],

我真的希望你们能帮助我,自己解决不了。 如果您需要更多详细信息,请联系我。 现在想不出其他任何东西。

非常感激!

沙岩

我在本地测试。 原来,我应该已经在服务器上对其进行了测试,因为在那里一切正常。

问题是我的php.ini:“ session.save_path”中的目录不存在,因此无法保存该会话。

确保该目录存在并且可写。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM