Heim  >  Artikel  >  Backend-Entwicklung  >  Über die Implementierung der Anmeldefunktion im Yii-Framework von PHP

Über die Implementierung der Anmeldefunktion im Yii-Framework von PHP

不言
不言Original
2018-06-15 16:10:001223Durchsuche

In diesem Artikel wird hauptsächlich die detaillierte Interpretation der Implementierung der Anmeldefunktion im Yii-Framework von PHP vorgestellt, einschließlich der Funktion der automatischen Anmeldung über Cookies. Freunde in Not können sich auf

Yii beziehen Anmeldemechanismus

Yii bietet bereits den grundlegendsten Benutzeranmeldemechanismus beim Generieren von Anwendungen. Wir verwenden Yii, um eine neue Anwendung zu generieren und das Verzeichnis protected/components einzugeben. Wir können die Datei UserIdentity.php wie folgt sehen:

public function authenticate() 
{ 
  $users=array( 
    // username => password 
    'demo'=>'demo', 
    'admin'=>'admin', 
  ); 
  if(!isset($users[$this->username])) 
    $this->errorCode=self::ERROR_USERNAME_INVALID; 
  elseif($users[$this->username]!==$this->password) 
    $this->errorCode=self::ERROR_PASSWORD_INVALID; 
  else 
    $this->errorCode=self::ERROR_NONE; 
  return !$this->errorCode; 
}

Diese Klasse besteht aus Komponenten und wird zu Beginn der Anwendung geladen. Sie wird für die grundlegendste Benutzerüberprüfung verwendet. Sie können sehen, dass die Funktion einfach zwei Benutzer, Demo und Admin, definiert. und das Passwort ist nur Demo und Admin. Wenn Ihre Benutzer sehr begrenzt sind, können Sie Benutzer hier direkt ändern und hinzufügen. Wenn es mehr gibt, werden wir später darüber sprechen. Mit dem if else unter der Funktion wird überprüft, ob der Benutzername und das Passwort gültig sind. Wenn ein Fehler auftritt, werden ERROR_USERNAME_INVALID und ERROR_PASSWORD_INVALID generiert. Im Allgemeinen wird hier eine echte Überprüfung von Benutzername und Passwort durchgeführt und eine grundlegende logische Verarbeitung nach der Anmeldung durchgeführt.
Sie können den Anmeldesteuerungsprozess nicht allein durch einen Blick auf diese Klasse sehen. Wenn wir den Prinzipien von Modell/Kontrolle/Ansicht folgen, können wir sehen, dass sich der Anmeldevorgang in diesen drei Aspekten widerspiegelt. Geben Sie zunächst den Ordner „Models“ ein und Sie können eine LoginForm-Klassendatei sehen. Diese Klasse erbt CFormModel und ist eine abgeleitete Klasse des Formularmodells, das Anmeldedaten und Geschäftslogik kapselt. Die Kernfunktionen lauten wie folgt:

/** 
 * Authenticates the password. 
 * This is the 'authenticate' validator as declared in rules(). 
 */ 
public function authenticate($attribute,$params) 
{ 
  $this->_identity=new UserIdentity($this->username,$this->password); 
  if(!$this->_identity->authenticate()) 
    $this->addError('password','用户名或密码错误'); 
} 
 
/** 
 * Logs in the user using the given username and password in the model. 
 * @return boolean whether login is successful 
 */ 
public function login() 
{ 
  if($this->_identity===null) 
  { 
    $this->_identity=new UserIdentity($this->username,$this->password); 
    $this->_identity->authenticate(); 
  } 
  if($this->_identity->errorCode===UserIdentity::ERROR_NONE) 
  { 
    $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days 
    Yii::app()->user->login($this->_identity,$duration); 
    return true; 
  } 
  else 
    return false; 
}

Die Authentifizierung verwendet hier die UserIdentity-Klasse, um den Benutzernamen und das Passwort zu überprüfen, während die Anmeldefunktion erkennt, ob die Die Identität des Benutzers wurde überprüft. Überprüfen Sie, ob die Einstellungen und der Fehlercode leer sind, und verwenden Sie schließlich die von Yii bereitgestellte Anmeldefunktion, um sich anzumelden. $duration kann den Gültigkeitszeitraum der Identität festlegen.
Wenn Sie sich Control noch einmal ansehen, gibt es in siteControler eine Aktion, die sich auf die Anmeldung bezieht, nämlich actionLogin. Die Funktion lautet wie folgt:

/** 
 * Displays the login page 
 */ 
public function actionLogin() 
{ 
  if (!defined('CRYPT_BLOWFISH')||!CRYPT_BLOWFISH) 
    throw new CHttpException(500,"This application requires that PHP was compiled with Blowfish support for crypt()."); 
 
  $model=new LoginForm; 
 
  // if it is ajax validation request 
  if(isset($_POST['ajax']) && $_POST['ajax']==='login-form') 
  { 
    echo CActiveForm::validate($model); 
    Yii::app()->end(); 
  } 
 
  // collect user input data 
  if(isset($_POST['LoginForm'])) 
  { 
    $model->attributes=$_POST['LoginForm']; 
    // validate user input and redirect to the previous page if valid 
    if($model->validate() && $model->login()) 
      $this->redirect(Yii::app()->user->returnUrl); 
  } 
  // display the login form 
  $this->render('login',array('model'=>$model)); 
}

Die Anmeldeaktion basiert auf LoginForm, um das POST-Formular zu überprüfen, um sich anzumelden oder eine neue Anmeldeseite zu erstellen.

Schließlich befindet sich die Ansichtsdatei login.php im Site-Ordner. Dies ist die Login-Schnittstelle, die Sie sehen.

Indem wir es sortieren, können wir die Benutzeranmeldelogik von Yii deutlich sehen. Nachdem Sie den Benutzernamen und das Passwort auf der Anmeldeoberfläche eingegeben haben, sendet das Formular die Daten an die Site/Anmeldung und instanziiert ein LoginForm-Formularmodell. und führt eine Anmeldeerkennung basierend auf der Validierungsfunktion und der Anmeldefunktion im Modell durch. Die Überprüfung des Passworts erfordert die Authentifizierungsfunktion und die Überprüfung der Authentifizierungs- und Anmeldefunktionen basierend auf der Authentifizierungsfunktion von UserIdentity. Wenn wir also die Anmeldelogik ändern, müssen LgoinForm und loginaction nicht geändert werden, und es reicht grundsätzlich aus, die Authentifizierungsfunktion von UserIdentity direkt zu ändern.

Die obige Analyse ist der von Yii automatisch generierte Logikverarbeitungscode für die Benutzeranmeldung. Sie sieht ziemlich gut aus, nicht wahr? Allerdings muss unser System im Allgemeinen den Zugriff vieler Benutzer unterstützen. Es ist natürlich irrational, Benutzernamen und Passwörter einfach im Code aufzulisten. Natürlich ist es ausgereifter, die Datenbank um Hilfe bei der Verwaltung zu bitten. Angenommen, wir erstellen eine Admin-Tabelle in unserer eigenen Datenbank gemäß der folgenden MySQL-Anweisung:

drop table if exists `admin`; 
create table `admin` ( 
  `admin_id` int unsigned not null auto_increment comment '主键', 
  `username` varchar(32) not null comment '登录名', 
  `psw` char(40) not null comment '登录密码(两次sha1)', 
  `nick` varchar(64) not null comment '昵称', 
  `add_time` datetime not null comment '创建时间', 
  `login_time` datetime null comment '最近登录时间', 
  unique key(`username`), 
  primary key (`admin_id`) 
) engine=innodb default charset=utf8 comment='管理员表';

Nachdem die Erstellung der MySQL-Tabelle abgeschlossen ist, verwenden wir gii zum Generieren Wenn wir das Admin-Modell verwenden, können wir zu UserIdentity.php in unserer ursprünglichen Komponente zurückkehren und die Authentifizierungsfunktion neu schreiben, um unsere eigene Benutzernamen- und Passwortüberprüfung zu implementieren. Aus Sicherheitsgründen wird das Passwort zweimal mit sha1 verschlüsselt, sodass das gesammelte Passwort zweimal mit sha1 verschlüsselt wird. Anschließend prüfen wir im von uns erstellten Admin, ob es einen Benutzer gibt, der dem im Formular eingegebenen Benutzernamen entspricht, und vergleichen ihn dann verschlüsseltes Passwort. Wenn alles erfolgreich ist, können die allgemeinen Informationen des Benutzers mithilfe der setState-Funktion auf das Benutzerfeld von Yii festgelegt werden, z. B. $this->setState('nick', $user->nick After this); Satz können Sie direkt Yii:app()->user->nick verwenden, um auf den Spitznamen des aktuell angemeldeten Benutzers zuzugreifen, ohne die Datenbank abzufragen. Und $user->login_time = date('Y-m-d H:i:s'); aktualisiert die Benutzeranmeldezeit und speichert sie durch Speichern im nächsten Satz in der Datenbank.

public function authenticate() 
{ 
  if(strlen($this->password) > 0) 
    $this->password = sha1(sha1($this->password)); 
  $user = Admin::model()->findByAttributes(array('username' => $this->username)); 
  if($user == null) 
    $this->errorCode=self::ERROR_USERNAME_INVALID; 
  elseif( !($user instanceof Admin) || ($user->psw != $this->password) ) 
    $this->errorCode=self::ERROR_PASSWORD_INVALID; 
  else 
  { 
    $this->setState('admin_id', $user->admin_id); 
    $this->setState('nick', $user->nick); 
    $this->setState('username', $user->username); 
    $user->login_time = date('Y-m-d H:i:s'); 
    $user->save(); 
    $this->errorCode=self::ERROR_NONE; 
  } 
  return !$this->errorCode; 
}

Und wenn Sie die Anmeldeschnittstelle ändern möchten, gehen Sie in die login.php im Site-Ordner in der Ansicht und spielen Sie so viel damit herum So wie Sie es möchten, damit unser eigener Anmeldevorgang abgeschlossen ist. Ist es nicht äußerst praktisch, Yii~

zu haben?

设置自动登陆
自动登录的原理很简单。主要就是利用cookie来实现的
在第一次登录的时候,如果登录成功并且选中了下次自动登录,那么就会把用户的认证信息保存到cookie中,cookie的有效期为1年或者几个月。

在下次登录的时候先判断cookie中是否存储了用户的信息,如果有则用cookie中存储的用户信息来登录,

配置User组件

首先在配置文件的components中设置user组件

    'user' => [
      'identityClass' => 'app\models\User',
      'enableAutoLogin' => true,
    ],

我们看到enableAutoLogin就是用来判断是否要启用自动登录功能,这个和界面上的下次自动登录无关。
只有在enableAutoLogin为true的情况下,如果选择了下次自动登录,那么就会把用户信息存储起来放到cookie中并设置cookie的有效期为3600*24*30秒,以用于下次登录

现在我们来看看Yii中是怎样实现的。

一、第一次登录存cookie

1、login 登录功能

  public function login($identity, $duration = 0)
  {
    if ($this->beforeLogin($identity, false, $duration)) {
      $this->switchIdentity($identity, $duration);
      $id = $identity->getId();
      $ip = Yii::$app->getRequest()->getUserIP();
      Yii::info("User '$id' logged in from $ip with duration $duration.", __METHOD__);
      $this->afterLogin($identity, false, $duration);
    }

    return !$this->getIsGuest();
  }

在这里,就是简单的登录,然后执行switchIdentity方法,设置认证信息。

2、switchIdentity设置认证信息

  public function switchIdentity($identity, $duration = 0)
  {
    $session = Yii::$app->getSession();
    if (!YII_ENV_TEST) {
      $session->regenerateID(true);
    }
    $this->setIdentity($identity);
    $session->remove($this->idParam);
    $session->remove($this->authTimeoutParam);
    if ($identity instanceof IdentityInterface) {
      $session->set($this->idParam, $identity->getId());
      if ($this->authTimeout !== null) {
        $session->set($this->authTimeoutParam, time() + $this->authTimeout);
      }
      if ($duration > 0 && $this->enableAutoLogin) {
        $this->sendIdentityCookie($identity, $duration);
      }
    } elseif ($this->enableAutoLogin) {
      Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
    }
  }

这个方法比较重要,在退出的时候也需要调用这个方法。

这个方法主要有三个功能
设置session的有效期
如果cookie的有效期大于0并且允许自动登录,那么就把用户的认证信息保存到cookie中
如果允许自动登录,删除cookie信息。这个是用于退出的时候调用的。退出的时候传递进来的$identity为null

  protected function sendIdentityCookie($identity, $duration)
  {
    $cookie = new Cookie($this->identityCookie);
    $cookie->value = json_encode([
      $identity->getId(),
      $identity->getAuthKey(),
      $duration,
    ]);
    $cookie->expire = time() + $duration;
    Yii::$app->getResponse()->getCookies()->add($cookie);
  }

存储在cookie中的用户信息包含有三个值:

  1. $identity->getId()

  2. $identity->getAuthKey()

  3. $duration

getId()和getAuthKey()是在IdentityInterface接口中的。我们也知道在设置User组件的时候,这个User Model是必须要实现IdentityInterface接口的。所以,可以在User Model中得到前两个值,第三值就是cookie的有效期。

二、自动从cookie登录

从上面我们知道用户的认证信息已经存储到cookie中了,那么下次的时候直接从cookie里面取信息然后设置就可以了。

1、AccessControl用户访问控制

Yii提供了AccessControl来判断用户是否登录,有了这个就不需要在每一个action里面再判断了 

 public function behaviors()
  {
    return [
      'access' => [
        'class' => AccessControl::className(),
        'only' => ['logout'],
        'rules' => [
          [
            'actions' => ['logout'],
            'allow' => true,
            'roles' => ['@'],
          ],
        ],
      ],
    ];
  }

2、getIsGuest、getIdentity判断是否认证用户

isGuest是自动登录过程中最重要的属性。
在上面的AccessControl访问控制里面通过IsGuest属性来判断是否是认证用户,然后在getIsGuest方法里面是调用getIdentity来获取用户信息,如果不为空就说明是认证用户,否则就是游客(未登录)。

 public function getIsGuest($checkSession = true)
  {
    return $this->getIdentity($checkSession) === null;
  }
  public function getIdentity($checkSession = true)
  {
    if ($this->_identity === false) {
      if ($checkSession) {
        $this->renewAuthStatus();
      } else {
        return null;
      }
    }

    return $this->_identity;
  }

3、renewAuthStatus 重新生成用户认证信息

 protected function renewAuthStatus()
  {
    $session = Yii::$app->getSession();
    $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null;

    if ($id === null) {
      $identity = null;
    } else {
      /** @var IdentityInterface $class */
      $class = $this->identityClass;
      $identity = $class::findIdentity($id);
    }

    $this->setIdentity($identity);

    if ($this->authTimeout !== null && $identity !== null) {
      $expire = $session->get($this->authTimeoutParam);
      if ($expire !== null && $expire < time()) {
        $this->logout(false);
      } else {
        $session->set($this->authTimeoutParam, time() + $this->authTimeout);
      }
    }

    if ($this->enableAutoLogin) {
      if ($this->getIsGuest()) {
        $this->loginByCookie();
      } elseif ($this->autoRenewCookie) {
        $this->renewIdentityCookie();
      }
    }
  }

这一部分先通过session来判断用户,因为用户登录后就已经存在于session中了。然后再判断如果是自动登录,那么就通过cookie信息来登录。

4、通过保存的Cookie信息来登录 loginByCookie

 protected function loginByCookie()
  {
    $name = $this->identityCookie[&#39;name&#39;];
    $value = Yii::$app->getRequest()->getCookies()->getValue($name);
    if ($value !== null) {
      $data = json_decode($value, true);
      if (count($data) === 3 && isset($data[0], $data[1], $data[2])) {
        list ($id, $authKey, $duration) = $data;
        /** @var IdentityInterface $class */
        $class = $this->identityClass;
        $identity = $class::findIdentity($id);
        if ($identity !== null && $identity->validateAuthKey($authKey)) {
          if ($this->beforeLogin($identity, true, $duration)) {
            $this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
            $ip = Yii::$app->getRequest()->getUserIP();
            Yii::info("User &#39;$id&#39; logged in from $ip via cookie.", __METHOD__);
            $this->afterLogin($identity, true, $duration);
          }
        } elseif ($identity !== null) {
          Yii::warning("Invalid auth key attempted for user &#39;$id&#39;: $authKey", __METHOD__);
        }
      }
    }
  }

先读取cookie值,然后$data = json_decode($value, true);反序列化为数组。

这个从上面的代码可以知道要想实现自动登录,这三个值都必须有值。另外,在User Model中还必须要实现findIdentity、validateAuthKey这两个方法。

登录完成后,还可以再重新设置cookie的有效期,这样便能一起有效下去了。

 $this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);

三、退出 logout

 public function logout($destroySession = true)
  {
    $identity = $this->getIdentity();
    if ($identity !== null && $this->beforeLogout($identity)) {
      $this->switchIdentity(null);
      $id = $identity->getId();
      $ip = Yii::$app->getRequest()->getUserIP();
      Yii::info("User '$id' logged out from $ip.", __METHOD__);
      if ($destroySession) {
        Yii::$app->getSession()->destroy();
      }
      $this->afterLogout($identity);
    }

    return $this->getIsGuest();
  }


  public function switchIdentity($identity, $duration = 0)
  {
    $session = Yii::$app->getSession();
    if (!YII_ENV_TEST) {
      $session->regenerateID(true);
    }
    $this->setIdentity($identity);
    $session->remove($this->idParam);
    $session->remove($this->authTimeoutParam);
    if ($identity instanceof IdentityInterface) {
      $session->set($this->idParam, $identity->getId());
      if ($this->authTimeout !== null) {
        $session->set($this->authTimeoutParam, time() + $this->authTimeout);
      }
      if ($duration > 0 && $this->enableAutoLogin) {
        $this->sendIdentityCookie($identity, $duration);
      }
    } elseif ($this->enableAutoLogin) {
      Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
    }
  }

退出的时候先把当前的认证设置为null,然后再判断如果是自动登录功能则再删除相关的cookie信息。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

如何实现修改yii2.0用户登录使用的user表为其它的表

关于php向访客和爬虫显示不同的内容代码

Das obige ist der detaillierte Inhalt vonÜber die Implementierung der Anmeldefunktion im Yii-Framework von PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn