2015-05-25 21 views
7

Tôi đang gặp rắc rối với các hành động sau "/ login" hành động tuyến đường trong lớp UsersController tôiYii2 Rest - Tác vụ tùy chỉnh và OPTIONS phương pháp

public function actionLogin(){ 
     $data = Yii::$app->getRequest()->getBodyParams(); 
     $model = new Usuario(); 

     //Validamos que se hayan recibido los campos 
     if(empty($data['email']) || empty($data['password'])){ 
      throw new \yii\web\BadRequestHttpException("Debe ingresar email y password"); 
     } 

     //Validamos usuario y contraseña 
     $usuario = $model->findByUsername($data['email']); 
     if(empty($usuario) || !$usuario->validatePassword($data['password'])){ 
      throw new \yii\web\UnauthorizedHttpException("Usuario y/o contraseña incorrectos"); 
     } 
     return $usuario; 
    } 

Tình hình là tôi đang sử dụng phương thức POST để thực hiện đăng nhập , và tôi gọi tuyến đường này từ một tên miền khác nhau, do thư viện frontend đầu tiên cố gắng gọi/route đăng nhập với phương pháp OPTIONS để kiểm tra nếu nó được cho phép hay không để gọi/đăng nhập với POST ..

vấn đề là rằng chức năng tích hợp của phần còn lại yii2 ActiveController chỉ dành cho/người dùng và/người dùng/{id}

Nếu tôi thêm thủ công/tuyến đăng nhập này để có sẵn trong cả POST và OPTIONS thông qua hành động verbFilter, thì yii Đang cố gắng thực sự gọi hành động đăng nhập với yêu cầu OPTIONS. Ý tôi là, nó đang cố gắng thực hiện đăng nhập. Tất nhiên nó không thể, bởi vì nó không gửi các trường email và mật khẩu, nhưng tôi có thể thấy một lỗi trong tệp nhật ký.

Vì vậy, câu hỏi của tôi là ... Có cách nào để định cấu hình chính xác hành động tuyến đường "tùy chỉnh" này và làm cho OPTIONS hoạt động một cách minh bạch không? Bởi vì tôi hy vọng rằng hành động đăng nhập đó sẽ không được thực hiện khi gọi nó với OPTIONS, nhưng thay vào đó để trả về trực tiếp các tiêu đề phương thức được phép OPTIONS.

Cập nhật Thông tin: quy tắc quản lý thêm URL

'urlManager' => [ 
     'enablePrettyUrl' => true, 
     'enableStrictParsing' => true, 
     'showScriptName' => true, 
     'rules' => [ 
      [ 
       'class' => 'yii\rest\UrlRule', 
       'controller' => ['v1/users'], 
       'pluralize' => false, 
       'tokens' => [ 
        '{id}' => '<id:\\w+>' 
       ] 
      ], 
      //Rutas usuario 
      'v1/login' => '/v1/users/login' 
     ],   
    ], 

Trả lời

0

Bạn cần phải đính kèm Cors lọc trong phương pháp điều khiển của bạn behaviours() (xem cách in official guide) với điều kiện sau:

  1. Cors lọc nên được xác định trước bộ lọc Xác thực/ủy quyền
  2. Quyền truy cập mở cho tất cả người dùng có thể hành động option trong AccessControl lọc

Trong trường hợp của bạn, UsersController có thể có như vậy behaviors() phương pháp:

public function behaviors() 
{ 
    return ArrayHelper::merge(
     [ 
      'cors' => [ 
       'class' => Cors::className(), 
      ], 
     ], 
     parent::behaviors(), 
     [ 
      'access' => [ 
       'class' => AccessControl::className(), 
       'rules' => [ 
        ['allow' => true, 'actions' => ['options']], 
       ] 
      ], 
     ] 
    ); 
} 
+0

@CreatorR Tôi đã thử giải pháp của bạn nhưng nó không hoạt động bởi vì, tôi nghĩ rằng, bạn không hiểu câu hỏi của tôi .. Loking tại mã nguồn của phần còn lại ActiveController, tôi thấy rằng một 'yii \ rest \ OptionsAction' hành động được cấu hình cho phương pháp tùy chọn .. Có cách nào để cấu hình khi gọi/đăng nhập với POST nó gọi actionLogin và khi gọi/đăng nhập với OPTIONS sau đó nó gọi là 'yii \ rest \ OptionsAction'? Cách nào tốt nhất để đạt được điều đó? Tôi nghĩ rằng đây là những gì tôi cần .. – edrian

+0

@edrian, sẽ là tuyệt vời để xem các quy tắc urlManager của bạn – CreatoR

+0

@CreatorR Tôi đã cập nhật bài đăng khi bạn yêu cầu – edrian

4

Theo mặc định lớp yii\rest\UrlRule sẽ áp dụng những mô hình cho bất kỳ thiết bị đầu cuối:

'patterns' => [ 
    'PUT,PATCH {id}' => 'update', 
    'DELETE {id}' => 'delete', 
    'GET,HEAD {id}' => 'view', 
    'POST' => 'create', 
    'GET,HEAD' => 'index', 
    '{id}' => 'options', 
    '' => 'options', 
] 

Điều này có nghĩa là mọi yêu cầu giữ động từ OPTIONS sẽ được chuyển hướng đến yii\rest\OptionsAction nếu sốcủa bạnđược viết bên trong một lớp mở rộng ActiveController.

Những gì tôi đề nghị là ghi đè patterns bằng cách chỉ sử dụng động từ được sử dụng làm hành động đăng nhập của bạn không cần bất kỳ hành động CRUD nào khác. thao tác này sẽ hoạt động với trường hợp của bạn:

'rules' => [ 
    [ 
     'class' => 'yii\rest\UrlRule', 
     'controller' => ['v1/users'], 
     'pluralize' => false, 
     'tokens' => [ 
      '{id}' => '<id:\\w+>' 
     ] 
    ], 
    [ 
     'class' => 'yii\rest\UrlRule', 
     'controller' => ['v1/login' => '/v1/users/login'], 
     'patterns' => [ 
      'POST' => 'login', 
      '' => 'options', 
     ] 
    ] 
], 

LƯU Ý: giải pháp bằng @CreatoR cũng là yêu cầu ở đây và chính xác như ông đã làm mà không cần xác định khóa. nếu không thì động từ OPTIONS sẽ bị từ chối nếu không được xác thực.


Trong trường hợp nếu đăng nhập hành động của bạn được định nghĩa dưới một lớp mở rộng yii\rest\Controller trực tiếp thay vì đi qua yii\rest\ActiveController (mà nên phù hợp với các hoạt động xác thực như không có CRUD cần thiết ở đây) thì quy tắc tương tự configs nên hoạt động tốt nhưng bạn sẽ cần phải tự thêm các actionOptions mã của bạn:

// grabbed from yii\rest\OptionsAction with a little work around 
private $_verbs = ['POST','OPTIONS']; 

public function actionOptions() 
{ 
    if (Yii::$app->getRequest()->getMethod() !== 'OPTIONS') { 
     Yii::$app->getResponse()->setStatusCode(405); 
    } 
    $options = $this->_verbs; 
    Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $options)); 
} 
2

tôi giải quyết vấn đề bằng cách mở rộng Co rs lớp lọc:

use Yii; 
use yii\filters\Cors; 

class CorsCustom extends Cors 

{ 
    public function beforeAction($action) 
    { 
     parent::beforeAction($action); 

     if (Yii::$app->getRequest()->getMethod() === 'OPTIONS') { 
      Yii::$app->getResponse()->getHeaders()->set('Allow', 'POST GET PUT'); 
      Yii::$app->end(); 
     } 

     return true; 
    } 
} 

và sau đó

public function behaviors() 
{ 
    $behaviors = parent::behaviors(); 
    unset($behaviors['authenticator']); 
    $behaviors['corsFilter'] = [ 
     'class' => CorsCustom::className(), 
    ]; 
    $behaviors['authenticator'] = [ 
     'class' => HttpBearerAuth::className(), 
     'optional' => ['login'] 
    ]; 
    return $behaviors; 
} 
+0

Sau đó, bạn sẽ thêm tùy chỉnh Cors này trong bộ điều khiển còn lại –

+0

Tôi đã cập nhật câu trả lời –

0
'rules' => [ 
    [ 
     'class' => 'yii\rest\UrlRule', 
     'controller' => ['v1/users'], 
     'pluralize' => false, 
     'tokens' => [ 
      '{id}' => '<id:\\w+>' 
     ] 
    ], 
    [ 
     'class' => 'yii\rest\UrlRule', 
     'controller' => ['v1/login' => '/v1/users/login'], 
     'patterns' => [ 
      'POST' => 'login', 
      'OPTIONS' => 'options', 
     ] 
    ] 
], 
1

Tôi có vấn đề này như vậy.

Đây là cách tôi cố định nó:

tôi đã thêm một tham số extraPatterns đối với quy tắc của tôi, như thế này:

'urlManager' => [ 
     'enablePrettyUrl' => true, 
     'showScriptName' => false, 
     'rules' => [ 
      [ 
       'class' => 'yii\rest\UrlRule', 
       'pluralize' => false, 
       'controller' => [ 
        'athlete', 
        'admin', 
        'address', 
        'program' 
       ], 
       'extraPatterns' => [ 
        'OPTIONS <action:\w+>' => 'options' 
       ] 
      ] 
     ], 
    ], 

Bằng cách này, hành động options sẽ được gọi cho tất cả các hành động tùy chỉnh mà tôi có trong bất kỳ bộ điều khiển nào.

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