2017-11-15 33 views
7

Tôi đã sử dụng xác thực zf2 để xác thực người dùng trong project.I đã lưu Harib trong bảng người dùng của tôi dưới dạng tên người dùng nhưng nếu tôi sử dụng tên người dùng Harib thì nó chấp nhận hoặc nếu tôi sử dụng harib thì không chấp nhận, tôi muốn loại bỏ độ nhạy trường hợp của tên người dùng để Harib hoặc harib truy cập như thế nào tôi sửa lỗi này?Làm thế nào để làm cho tên người dùng không nhạy cảm trong zf2

Đây là mã của tôi:

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

và đây được đăng nhập mẫu mã của tôi:

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

thế nào chúng ta loại bỏ nhạy trường hợp tên người dùng vì vậy cả hai Harib hoặc harib chấp nhận?

+0

cơ sở dữ liệu gì bạn đang sử dụng? – drew010

+0

Tôi đã sử dụng cơ sở dữ liệu mongodb –

+0

Trong trường hợp đó, bạn nên tạo một [chỉ số phân biệt chữ hoa chữ thường] (https://docs.mongodb.com/manual/core/index-case-insensitive/) cho trường tên người dùng để khi cơ sở dữ liệu adapter tìm kiếm cho nó, nó sẽ tìm thấy hồ sơ bất kể trường hợp. – drew010

Trả lời

2

Thêm bộ lọc StringToLower vào loginform trên phần tử user_id.

Đối với điều này, lớp định nghĩa loginform phải thực hiện InputFilterProviderInterface và bạn phải thêm trong phương pháp getInputFilterSpecification như sau của bạn:

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

Vì vậy, bạn được đảm bảo rằng giá trị trả lại trong bài là chữ thường.

+0

Xin chào @Alian Promirol Tôi đã đính kèm mã mẫu đăng nhập của mình, bạn có thể cho tôi biết tôi có thay đổi gì trong biểu mẫu không? –

+0

Cá nhân, tôi thích giao diện 'InputFilterProviderInterface' hơn' InputFilterAwareInterface', tôi không thực hiện phương thức 'getInputFilter()' trừ khi tôi muốn thay đổi hành vi mặc định của ZF2 và tôi thực hiện phương thức 'getInputFilterSpecification()' như được hiển thị trong câu trả lời của tôi. –

1

Bạn có thể thực hiện việc này theo hai cách. Bạn có thể tạo bộ điều hợp xác thực tùy chỉnh hoặc ghi đè phương thức của bộ điều hợp xác thực mặc định. Tôi khuyên bạn nên ghi đè phương thức đó dễ hơn tạo bộ điều hợp tùy chỉnh.

Vì vậy, đây là phương pháp CredentialTreatmentAdapter::authenticateCreateSelect(). Nếu bạn tra cứu khoảng 94 dòng (của zf 2.5) của phương thức đó từ zend-authentication thành phần thì bạn sẽ tìm thấy dòng sau.

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

Ở đây chúng tôi sẽ thực hiện thay đổi. Bây giờ, hãy ghi đè phương thức đó bằng cách mở rộng Zend\Authentication\Adapter\DbTable. Chúng tôi sẽ thực hiện một mệnh đề where mà sẽ tìm kiếm cho cả hai Harib hoặc harib do đó. Xem phần mở rộng sau đây 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; 
    } 
} 

Bộ điều hợp xác thực tùy chỉnh đã sẵn sàng. Bạn cần phải sử dụng cái này bên trong nhà máy cho dịch vụ xác thực thay vì Zend\Authentication\Adapter\DbTable như sau

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

Tất cả bây giờ được thiết lập. Phương thức ghi đè đó nên được gọi bất cứ khi nào bạn gọi phương thức này trong phương thức điều khiển của mình:

$authResult = $authService->authenticate(); 

Điều này không được kiểm tra. Vì vậy, bạn có thể cần phải thay đổi những thứ bạn cần. Hãy sửa chúng nếu cần.

Hy vọng điều này sẽ giúp ích cho bạn!

+0

Hi @unclexo i sử dụng mongodb không sql –

+0

Tôi không nhận thấy rằng bạn đang sử dụng mongodb. Tôi thực sự xin lỗi vì điều đó. Tuy nhiên bạn sẽ có thể thể hiện 'identityClass'? Hoặc một cái gì đó mà bạn đang đối phó với mongodb? – unclexo

+0

Hi @unclexo Tôi đã sử dụng xác thực zend và bạn thấy tất cả mã của tôi ở trên –

2

Vì bạn đang sử dụng MongoDB, bạn có thể sử dụng regex để lấy tên người dùng từ cơ sở dữ liệu.

Đề xuất 1:

Trong ví dụ của bạn mà sẽ là:

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

Đề xuất 2:

Bạn có thể sử dụng $ options => i cho trường hợp tìm kiếm không nhạy cảm. Đưa ra một số ví dụ có thể cần thiết cho chuỗi trận đấu.

trường hợp chính xác không nhạy cảm chuỗi

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

Có chuỗi

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

Bắt đầu với chuỗi

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

End với chuỗi

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

Không Có chuỗi

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

Thông tin thêm về regex trong MongoDB đây: https://docs.mongodb.com/manual/reference/operator/query/regex/index.html

Các vấn đề liên quan