7

Ich benutze zf2 Authentifizierung für Benutzer in meinem Projekt zu authentifizieren.Ich habe Harib in meiner Benutzertabelle als Benutzername gespeichert, aber wenn ich meinen Benutzernamen Harib dann seine Annahme oder wenn ich harib dann verwenden nicht akzeptieren, ich möchte die Groß- und Kleinschreibung des Benutzernamens entfernen, so dass sowohl Harib als auch Harib Zugriff wie ich das beheben?Wie man Benutzernamen in zf2 case insensitive macht

Hier ist mein Code:

public function loginAction() 
{ 
    $this->layout('layout/login-layout.phtml'); 
    $login_error = false; 
    $loginForm = new LoginForm(); 
    $form_elements = json_encode($loginForm->form_elements); 
    if ($this->request->isPost()) { 
     $post = $this->request->getPost(); 
     $loginForm->setData($post); 
     if ($loginForm->isValid()) { 
      $hashed_string = ''; 
      if(
       array_key_exists('hashed_input' , $post) && 
       $post['hashed_input'] != '' && 
       strpos(urldecode($this->params('redirect')) , 'programdetailrequest') !== false 
      ) { 
       $hashed_string = $post['hashed_input']; 
      } 
      $data = $loginForm->getData(); 
      $authService = $this->getServiceLocator()->get('doctrine.authenticationservice.odm_default'); 
      $adapter = $authService->getAdapter(); 
      $adapter->setIdentityValue($data['username']); 
      $adapter->setCredentialValue(md5($data['password'])); 
      $authResult = $authService->authenticate(); 
      if($authResult->isValid()){ 
       $identity = $authResult->getIdentity(); 
       if(is_object($identity) && method_exists($identity, 'getData')){ 
        $user_data = $identity->getData(); 
        $authService->getStorage()->write($identity); 
        // for remeber checkbox 
        if ($post['rememberme']) { 
         $token = new UserToken(); 
         $dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default'); 
         //if same user already running from other browser then remove previous token. 
         $check_token = $dm->getRepository('Admin\Document\UserToken')->findOneBy(array("user_id.id" => $user_data['id'])); 
         if (is_object($check_token) && !is_null($check_token)) { 
          $remove_token = $dm->createQueryBuilder('Admin\Document\UserToken') 
           ->remove() 
           ->field('id')->equals($check_token->id) 
           ->getQuery()->execute(); 
         } 
         //create token 
         $user = $dm->getRepository('Admin\Document\User')->findOneBy(array("id" => $user_data['id'])); 
         $token->setProperty('user_id', $user); 
         $token->setProperty('dataentered', new \MongoDate()); 
         $dm->persist($token); 
         $dm->flush($token); 
         //create cookie 
         if(is_object($token) && property_exists($token, 'id')){ 
          $time = time() + (60 * 60 * 24 * 30); // 1 month 
          setcookie('token', $token->getProperty('id'), $time, '/'); 
         } 
        } 
        if ($user_data['user_type'] == 'onlinemarketer') { 
         $this->redirect()->toRoute('admin_program_meta'); 
        } elseif ($user_data['user_type'] == 'bucharestofficemanager') { 
         $this->redirect()->toRoute('admin_program_detail_request'); 
        } else { 
         if ($this->params('redirect') && urldecode($this->params('redirect')) !== '/logout/') { 
          $server_url = $this->getRequest()->getUri()->getScheme() . '://' . $this->getRequest()->getUri()->getHost().urldecode($this->params('redirect') . $hashed_string); 
          return $this->redirect()->toUrl($server_url); 
         } 
         return $this->redirect()->toRoute('admin_index'); 
        } 
       } 
      } else { 
       $identity = false; 
       $login_error = true; 
      } 
     } 
    } 
    return new ViewModel(array(
      'loginForm' => $loginForm, 
      'form_elements' =>$form_elements, 
      'login_error' => $login_error, 
    )); 
} 

und hier ist mein Login-Formular Code:

<?php 
namespace Admin\Form; 

use Zend\Form\Form; 
use Zend\Form\Element; 
use Zend\InputFilter\InputFilterAwareInterface; 
use Zend\InputFilter\InputFilter; 
use Zend\InputFilter\Factory as InputFactory; 

class LoginForm extends Form implements InputFilterAwareInterface 
{ 
protected $inputFilter; 
public $form_elements = array(
    array(
     'name' => 'username', 
     'attributes' => array(
      'id' => 'username', 
      'type' => 'text', 
      'error_msg' => 'Enter Valid Username', 
      'data-parsley-required' => 'true', 
      'data-parsley-pattern' => '^[a-zA-Z0-9_\.\-]{1,50}$', 
      'data-parsley-trigger' => 'change' 
     ), 
     'options' => array(
      'label' => 'User Name' 
     ), 
     'validation' => array(
      'required'=>true, 
      'filters'=> array(
       array('name'=>'StripTags'), 
       array('name'=>'StringTrim') 
      ), 
      'validators'=>array(
       array('name'=>'Regex', 
        'options'=> array(
         'pattern' => '/^[a-z0-9_.-]{1,50}+$/', // contain only a to z 0 to 9 underscore, hypen and space, min 1 max 50 
         'pattern_js' => '^[a-zA-Z0-9_\.\-]{1,50}$' 
        ) 
       ) 
      ) 
     ) 
    ), 
    array(
     'name' => 'password', 
     'attributes' => array(
      'id' => 'password', 
      'type' => 'password', 
      'error_msg' => 'Enter Valid Password', 
      'data-parsley-required' => 'true', 
      'data-parsley-pattern' => '^[a-zA-Z0-9_\.\-]{6,25}$', 
      'data-parsley-trigger' => 'change' 
     ), 
     'options' => array(
      'label' => 'Password' 
     ), 
     'validation' => array(
      'required' => true, 
      'filters'=> array(
       array('name'=>'StripTags'), 
       array('name'=>'StringTrim') 
      ), 
      'validators'=>array(
       array('name'=>'Regex', 
        'options'=> array(
         'pattern' => '/^[a-z0-9_.-]{6,25}+$/', // contain only a to z 0 to 9 underscore, hypen and space, min 1 max 50 
         'pattern_js' => '^[a-zA-Z0-9_\.\-]{6,25}$' 
        ) 
       ) 
      ) 
     ) 
    ), 
    array(
     'name' => 'hashed_input', 
     'attributes' => array(
      'type' => 'hidden', 
      'id' => 'hashed_input', 
      'value' => '' 
     ) 
    ), 
    array(
     'name' => 'rememberme', 
     'attributes' => array(
      'value' => 1, 
      'id' => 'rememberme', 
      'type' => 'Checkbox' 
     ), 
     'options' => array(
      'label' => 'Remember Me', 
      'use_hidden_element' => false, 
     ) 
    ), 
    array(
     'name' => 'submit', 
     'attributes' => array(
      'type' => 'submit', 
      'value' => 'Log in', 
      'id' => 'submitbutton' 
     ) 
    ) 
); 
public function __construct() 
{ 
    parent::__construct('user'); 
    $this->setAttribute('method', 'post'); 
    $this->setAttribute('data-parsley-validate', ''); 
    $this->setAttribute('data-elements', json_encode($this->form_elements)); 
    $this->setAttribute('autocomplete', 'off'); 
    for($i=0;$i<count($this->form_elements);$i++){ 
     $elements=$this->form_elements[$i]; 
     $this->add($elements); 
    } 
} 
public function getInputFilter($action=false) 
{ 
    if(!$this->inputFilter){ 
     $inputFilter = new InputFilter(); 
     $factory = new InputFactory(); 
     for($i=0;$i<count($this->form_elements);$i++){ 
      if(array_key_exists('validation',$this->form_elements[$i])){  
       $this->form_elements[$i]['validation']['name']=$this->form_elements[$i]['name']; 
       $inputFilter->add($factory->createInput($this->form_elements[$i]['validation'])); 
      } 
     } 
     $this->inputFilter = $inputFilter; 
    } 
    return $this->inputFilter; 
} 
} 

wie wir Groß- und Kleinschreibung des Benutzernamens so beide Harib oder Harib akzeptiert entfernen?

+0

Welche Datenbank verwenden Sie? – drew010

+0

Ich verwendete mongodb Datenbank –

+0

In diesem Fall sollten Sie einen Index erstellen [case-insensitive Index] (https://docs.mongodb.com/manual/core/index-case-insensitive/) für das Feld Benutzername so, wenn die Datenbank Adapter sucht danach, es wird den Datensatz unabhängig von der Groß-/Kleinschreibung finden. – drew010

Antwort

2

Fügen Sie einen Filter StringToLower in Ihrem loginform auf dem Element user_id hinzu.

Hierzu ist die Klasse, die Ihre loginform definiert muss InputFilterProviderInterface implementieren und Sie müssen in der getInputFilterSpecification Methode wie folgt hinzufügen:

public function getInputFilterSpecification() 
{ 
    return [ 
     'username' => [ 
      'name' => 'username', 
      'required' => true, 
      'filters' => [ 
       'name' => 'StringToLower', 
       'name'=>'StripTags', 
       'name'=>'StringTrim' 
      ], 
      validators => [ 
       [ 
        'name'=>'Regex', 
        'options'=> [ 
         'pattern' => '/^[a-z0-9_.-]{1,50}+$/', 
         'pattern_js' => '^[a-zA-Z0-9_\.\-]{1,50}$' 
        ] 
       ] 
      ] 
     ], 
     'password' => [ 
      'name' => 'password', 
      'required' => true, 
      'filters' => [ 
       array('name'=>'StripTags'), 
       array('name'=>'StringTrim') 
      ], 
      'validators' => [ 
       [ 
        'name'=>'Regex', 
        'options'=> [ 
        'pattern' => '/^[a-z0-9_.-]{6,25}+$/', 
        'pattern_js' => '^[a-zA-Z0-9_\.\-]{6,25}$' 
        ] 
       ] 
      ] 
     ] 
    ]; 
} 

So können Sie sicher sein, dass der Wert in der Post zurück in Klein ist.

+0

Hallo @Alian Promirol Ich habe meine Login-Formular-Code, können Sie mir sagen, was ich in Form ändern? –

+0

Persönlich bevorzuge ich die 'InputFilterProviderInterface' Schnittstelle anstelle von 'InputFilterAwareInterface', ich implementiere die' getInputFilter()' Methode nicht, außer wenn ich das Standardverhalten von ZF2 ändern möchte und ich die 'getInputFilterSpecification()' Methode wie gezeigt implementiere in meiner Antwort. –

1

Sie können dies auf zwei Arten tun. Entweder Sie können einen benutzerdefinierten Authentifizierungsadapter erstellen oder eine Methode des Standardauthentifizierungsadapters überschreiben. Ich empfehle, diese Methode zu überschreiben, die einfacher ist als das Erstellen eines benutzerdefinierten Adapters.

Also hier ist die Methode CredentialTreatmentAdapter::authenticateCreateSelect(). Wenn Sie in der Zeile 94 Zeile (von ZF 2.5) dieser Methode von zend-authentication Komponente suchen dann würden Sie die folgende Zeile finden.

$dbSelect->from($this->tableName) 
    ->columns(['*', $credentialExpression]) 
    // See the making of where clause 
    ->where(new SqlOp($this->identityColumn, '=', $this->identity)); 

Hier werden wir unsere Änderungen vornehmen. Jetzt können wir diese Methode überschreiben, indem wir Zend\Authentication\Adapter\DbTable erweitern. Wir würden eine Where-Klausel machen, die sowohl nach Harib als auch nach harib suchen würde. Siehe die folgende erweiterte CustomDbTable::class.

<?php 
namespace Define\Your\Own\Namespace; 

use Zend\Authentication\Adapter\DbTable; 

class CustomDbTable extends DbTable 
{ 
    protected function authenticateCreateSelect() 
    { 
     // build credential expression 
     if (empty($this->credentialTreatment) || (strpos($this->credentialTreatment, '?') === false)) { 
      $this->credentialTreatment = '?'; 
     } 

     $credentialExpression = new SqlExpr(
      '(CASE WHEN ?' . ' = ' . $this->credentialTreatment . ' THEN 1 ELSE 0 END) AS ?', 
      array($this->credentialColumn, $this->credential, 'zend_auth_credential_match'), 
      array(SqlExpr::TYPE_IDENTIFIER, SqlExpr::TYPE_VALUE, SqlExpr::TYPE_IDENTIFIER) 
     ); 

     // Here is the catch 
     $where = new \Zend\Db\Sql\Where(); 
     $where->nest() 
      ->equalTo($this->identityColumn, $this->identity) 
      ->or 
      ->equalTo($this->identityColumn, strtolower($this->identity)) 
      ->unnest(); 

     // get select 
     $dbSelect = clone $this->getDbSelect(); 
     $dbSelect->from($this->tableName) 
      ->columns(array('*', $credentialExpression)) 
      ->where($where); // Here we are making our own where clause 

     return $dbSelect; 
    } 
} 

Jetzt benutzerdefinierte Authentifizierung Adapter ist fertig. Sie benötigen diese eine in der Fabrik für Authentifizierungsdienst zu verwenden, anstatt von Zend\Authentication\Adapter\DbTable als

'factories' => array(

    // Auth service 
    'AuthService' => function($sm) { 
     $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 

     // Use CustomDbTable instead of DbTable here 
     $customDbTable = new CustomDbTable($dbAdapter, 'tableName', 'usernameColumn', 'passwordColumn', 'MD5(?)'); 
     $authService = new AuthenticationService(); 
     $authService->setAdapter($customDbTable); 

     return $authService; 
    }, 
), 

All folgt sind nun eingestellt. Diese überschriebene Methode sollte aufgerufen werden, wenn Sie diese in Ihrer Controller-Methode aufrufen:

$authResult = $authService->authenticate(); 

Dies wird nicht getestet. Also müssen Sie möglicherweise Dinge ändern, wo Sie brauchen. Bitte korrigieren Sie diese bei Bedarf.

Hoffe das würde dir helfen!

+0

Hallo @unclexo ich benutzte mongodb nicht sql –

+0

Ich habe nicht bemerkt, dass Sie mongodb verwenden. Das tut mir wirklich leid. Aber könntest du "identityClass" vorführen? Oder etwas, wo du mit Mongodb zu tun hast? – unclexo

+0

Hi @unclexo Ich habe Zend-Authentifizierung verwendet und Sie haben alle meinen Code über –

2

Da Sie MongoDB verwenden, können Sie eine Regex verwenden, um den Benutzernamen aus der Datenbank abzurufen.

Vorschlag 1:

In Ihrem Beispiel wäre das:

db.stuff.find({ foo: /^bar$/i }); 

Vorschlag 2:

Sie $ Optionen verwenden => i für Groß- und Kleinschreibung Suche. Geben Sie einige mögliche Beispiele an, die für die Zeichenfolgenübereinstimmung erforderlich sind.

Exakte Groß- und Kleinschreibung Zeichenfolge

db.collection.find({name:{'$regex' : '^string$', '$options' : 'i'}}) 

Enthält String

db.collection.find({name:{'$regex' : 'string', '$options' : 'i'}}) 

beginnen mit String

db.collection.find({name:{'$regex' : '^string', '$options' : 'i'}}) 

Ende mit einer Schnur

db.collection.find({name:{'$regex' : 'string$', '$options' : 'i'}}) 
Hat

nicht Enthält String

db.collection.find({name:{'$regex' : '^((?!string).)*$', '$options' : 'i'}}) 

Mehr über regex in MongoDB hier: https://docs.mongodb.com/manual/reference/operator/query/regex/index.html