doushanmo7024
2015-11-17 14:57
浏览 90

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

I'm pretty frustrated. Already searched the s**t out of Google and SO...

I'm using the basic Yii2 template and try to implement User Login, but can't figure out why it won't log me in.

The problem is, I have to use an already existing database with a horrible structure:

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

As you can see, "Alias" = Username and password is a bcrypt hash of the user's password.

And here is my StudyController.php (excerpt):

<?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,
    ]);
}

And here is my LoginForm.php Model:

<?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;
    }
}

And the User Model which implements the 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;
    }
}

And last but not least, the Login View:

<?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}
<div class=\"col-lg-3\">{input}</div>
<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>
<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>

When I open the Login Form and insert a valid username and password, it brings me back to the Login Form. Looked into Gii Logs and here is the output: Gii Output As you can see, it obviously logged me in. Still can't go to another subpage..

The cookie "_identity" is there and my own database queries in the User.php Model seem to work fine btw (otherwise the screenshot wouldn't show the right userID).

Here's the user components part of my config:

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

I really hope you guys can help me, can't figure it out by myself. If you need more details, just hit me up. Can't think of anything else right now.

Much appreciated!

Shayan

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

相关推荐 更多相似问题