2017-11-15 105 views
7

Użyłem uwierzytelniania zf2 dla uwierzytelnienia użytkownika w moim projekcie. Zapisałem Harib w mojej tablicy użytkownika jako nazwę użytkownika, ale jeśli używam mojej nazwy użytkownika Harib, to akceptuję lub jeśli używam harib, to jego nie akceptuję, chcę usunąć wielkość liter nazwy użytkownika, aby zarówno Harib, jak i Harib mieli dostęp do tego, jak to naprawić?Jak ustawić wielkość liter w nazwie użytkownika zf2

Oto mój kod:

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

i tu jest mój login kod forma:

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

jak usuwamy wielkości liter nazwy użytkownika więc zarówno Harib lub harib akceptowane?

+0

Co baza danych używasz? – drew010

+0

Użyłem bazy danych mongodb –

+0

W takim przypadku powinieneś utworzyć indeks nie uwzględniający wielkości liter (https://docs.mongodb.com/manual/core/index-case-insensitive/) dla pola nazwy użytkownika, więc gdy baza danych adapter wyszukuje, znajdzie rekord niezależnie od wielkości liter. – drew010

Odpowiedz

2

Dodaj filtr StringToLower do swojego loginform elementu user_id.

Za to klasa, która określa loginform musi wdrożyć InputFilterProviderInterface i należy dodać w metodzie getInputFilterSpecification następująco:

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}$' 
        ] 
       ] 
      ] 
     ] 
    ]; 
} 

więc masz pewność, że wartość zwracana w poście jest małymi literami.

+0

Witam @ Alian Promirol Załączam mój kod formularza logowania, czy możesz mi powiedzieć, co zmienię w formularzu? –

+0

Osobiście wolę interfejs 'InputFilterProviderInterface' zamiast' InputFilterAwareInterface', nie implementuję metody 'getInputFilter()', chyba że chcę zmienić domyślne zachowanie ZF2 i implementuję metodę 'getInputFilterSpecification()' jak pokazano w mojej odpowiedzi. –

1

Możesz to zrobić na dwa sposoby. Możesz utworzyć niestandardowy adapter uwierzytelniania lub przesłonić metodę domyślnego adaptera uwierzytelniania. Zalecam, aby zastąpić tę metodę łatwiejszą niż tworzenie niestandardowego adaptera. To jest metoda CredentialTreatmentAdapter::authenticateCreateSelect(). Jeśli spojrzysz w górę wokół linii 94 (zf 2.5) tej metody z komponentu zend-authentication, wówczas znajdziesz następujący wiersz.

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

Tutaj zamierzamy wprowadzić nasze zmiany. Teraz możemy zastąpić tę metodę przez rozszerzenie Zend\Authentication\Adapter\DbTable. Zrobilibyśmy klauzulę where, która wyszukałaby zarówno Harib jak i harib. Zobacz następujący rozszerzony 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; 
    } 
} 

Teraz niestandardowy adapter uwierzytelniania jest gotowy. Trzeba korzystać z tego jeden w fabryce za usługi uwierzytelniania zamiast Zend\Authentication\Adapter\DbTable następująco

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

Wszystkie są teraz ustawione. Ta przesłonięta metoda powinna zostać wywołana za każdym razem, gdy wywołasz tę metodę w kontrolerze:

$authResult = $authService->authenticate(); 

To nie jest testowane. Być może będziesz musiał zmienić rzeczy tam, gdzie potrzebujesz. Napraw je w razie potrzeby.

Mam nadzieję, że to pomoże!

+0

Hi @unclexo użyłem mongodb nie sql –

+0

Nie zauważyłem, że używasz mongodb. Naprawdę przepraszam za to. Czy byłbyś jednak w stanie pochwalić się 'identityClass'? Lub coś, co masz do czynienia z mongodb? – unclexo

+0

Hi @unclexo Użyłem uwierzytelniania zend i widziałeś cały mój kod powyżej –

2

Ponieważ używasz MongoDB, możesz użyć wyrażenia regularnego, aby pobrać nazwę użytkownika z bazy danych.

Propozycja 1:

W przykładzie byłoby to:

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

Propozycja 2:

Można użyć $ options => I przez przypadek niewrażliwego wyszukiwania. Podanie niektórych możliwych przykładów wymaganych do dopasowania ciągów.

Dokładna wielkość liter ma znaczenie ciąg

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

Zawiera String

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

Zacznij sznurkiem

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

kończyć ciągiem

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

Nie Zawiera ciąg

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

Więcej o regex w MongoDB tutaj: https://docs.mongodb.com/manual/reference/operator/query/regex/index.html