2016-08-30 1 views
2

완전한 블로킹 된 RBAC를 사용하지 않고 게시물의 소유자/작성자에게 컨트롤러 작업을 제한하는 쉬운 방법이 있습니까?Yii2의 게시물 작성자에게 컨트롤러 작업 제한

public function actionUpdate($id) { 
    $model = $this->findModel($id); 
    if ($model->user_id != Yii::$app->user->identity->id) { 
     throw new NotFoundHttpException('The requested page does not exist.'); 
    } 
} 

하지만 난 $model 그게 전부가 편집중인 만든 사용자에게 특정 컨트롤러를 제한 할 수있는 더 좋은 방법이 있어야합니다 생각 :

는 지금은 모든 컨트롤러에이 일을하고 있습니다.

답변

3

1) 권장되는 방법에 대한

use yii\filters\AccessControl; 

class SiteController extends Controller 
{ 
    public function behaviors() 
    { 
     return [ 
      'access' => [ 
       'class' => AccessControl::className(), 
       'only' => ['update','delete'], 
       'rules' => [ 
        [ 
         'actions' => ['update'], 
         'allow' => false, 
         'denyCallback' => function ($rule, $action) { //PHP callable that should be called when this rule will deny the access. 
          //Write your logic here to deny the action 
          throw new \Exception('You are not allowed to access this page'); 
         } 
        ], 
       ], 
      ], 
     ]; 
    } 

    public function actionUpdate() 
    { 
     return $this->render('update'); 
    } 
} 

은 RBAC 및 규칙을 사용하는 것입니다. 전용 섹션에 따라 official docs에 잘 설명되어 있습니다. 저자 ID가 PARAMS를 통해 전달 된 현재 사용자 ID와 일치하는지 검사 규칙의

예 :

namespace app\rbac; 

use yii\rbac\Rule; 

/** 
* Checks if authorID matches user passed via params 
*/ 
class AuthorRule extends Rule 
{ 
    public $name = 'isAuthor'; 

    /** 
    * @param string|integer $user the user ID. 
    * @param Item $item the role or permission that this rule is associated with 
    * @param array $params parameters passed to ManagerInterface::checkAccess(). 
    * @return boolean a value indicating whether the rule permits the role or permission it is associated with. 
    */ 
    public function execute($user, $item, $params) 
    { 
     return isset($params['post']) ? $params['post']->createdBy == $user : false; 
    } 
} 

이 그런 권한을 기존과 넥타이 필요는 (확장 이전 또는 수행 할 수 있습니다) :

당신은 사용자가이 같은 게시물을 업데이트 할 수 있습니다

$auth = Yii::$app->authManager; 

// add the rule 
$rule = new \app\rbac\AuthorRule; 
$auth->add($rule); 

// add the "updateOwnPost" permission and associate the rule with it. 
$updateOwnPost = $auth->createPermission('updateOwnPost'); 
$updateOwnPost->description = 'Update own post'; 
$updateOwnPost->ruleName = $rule->name; 
$auth->add($updateOwnPost); 

// "updateOwnPost" will be used from "updatePost" 
$auth->addChild($updateOwnPost, $updatePost); 

// allow "author" to update their own posts 
$auth->addChild($author, $updateOwnPost); 
은 그럼 당신은 확인할 수 있습니다

use yii\web\ForbiddenHttpException; 
use Yii; 

public function actionUpdate($id) 
{ 
    $model = $this->findModel($id); 
    if (!Yii::$app->user->can('updatePost', ['post' => $model])) { 
     throw new ForbiddenHttpException('You are not allowed to edit this post'); 
    } 

    ... 
} 

또한 모델을 먼저 찾았을 때 사용자가 편집 할 수있는 권한이 없다는 사실을 알게되면 404 금지 된 예외는 404가 아닌 발견 된 것이기 때문에 논리적으로 던지는 것이 좋습니다.

AccessControl 행동에 그런 규칙을 포함하는 것을 잊지 마십시오

[ 
    'allow' => true, 
    'actions' => ['update'], 
    'roles' => ['@'], 
], 

은이 컨트롤러의 update 행동 만 명을 제외한 권한이 부여 된 사용자가 액세스 할 수 있다는 것을 의미한다.

2)는 RBAC를 사용하지 않으려는 어떤 이유로, 당신은 당신의 방법을 사용할 수있는 경우 :

use yii\web\ForbiddenHttpException; 

public function actionUpdate($id) 
{ 
    $model = $this->findModel($id); 
    if ($model->user_id != Yii::$app->user->id) { 
     throw new ForbiddenHttpException('You are not allowed to edit this post.'); 
    } 

    ... 
} 

는 도우미 메서드에이 논리를 이동하여이 검사에서 추상적 할 수있는이 문제를 개선하기 위해 :

namespace app\posts\components; 

use Yii; 

class PostPermission 
{ 
    /** 
    * @param $model Post 
    * @return boolean 
    */ 
    public static function allowedToUpdate($model) 
    { 
     return $model->user_id = Yii:$app->user->id; 
    } 
} 

는 그런 다음과 같이 호출 :

use app\posts\components\PostPermission; 
use yii\web\ForbiddenHttpException; 

if (!PostPermission::allowedToUpdate($model) { 
    throw new ForbiddenHttpException('You are not allowed to edit this post.'); 
} 

그것은 단지 예일뿐입니다. 메서드는 정적이어서는 안되며 $model을 사용하여 인스턴스를 생성 할 수 있습니다.

Post 모델에 직접 메소드를 작성할 수는 있지만, 그러한 논리로 모델을 오염시키지 않는 것이 좋습니다. 당신이

use yii\web\NotFoundHttpException; 

/** 
* @param integer $id 
* @return Post 
* @throws NotFoundHttpException 
*/ 
protected function findModel($id) 
{ 
    $query = Post::find()->where(['id' => $id]); 
    if (!Yii::$app->user->is_admin) { // replace with your own check 
     $query->andWhere(['user_id' => Yii::$app->user->id]); 
    } 
    $model = $query->one(); 
    if ($model) { 
     return $model; 
    } else { 
     throw new NotFoundHttpException('This post does not exist.'); 
    } 
} 

다음 :

use yii\web\NotFoundHttpException; 

/** 
* @param integer $id 
* @return Post 
* @throws NotFoundHttpException 
*/ 
protected function findModel($id) 
{ 
    $model = Post::find(['id'=> $id, 'user_id' => Yii::$app->user->id])->one(); 
    if ($model) { 
     return $model; 
    } else { 
     throw new NotFoundHttpException('This post does not exist.'); 
    } 
} 

이 사이트 관리자를위한 개선 될 수있다 : 내가 조언 할 수

3) 또 다른 모델을 찾을 때 현재 사용자에게 초기 범위를 제한하는 것입니다 쓰기 만 :

public function actionUpdate($id) 
{ 
    $model = $this->findModel($id); 
    ... 
} 

두 가지 경우 모두 (모델을 찾을 수없고 현재 사용자가 편집 할 수 없음), 404 Not Found 예외가 발생합니다. 다른 측면에서 볼 때 아무 문제가 없습니다. 기술적으로이 사용자의 경우이 모델은 존재하지 않기 때문에 (저자이기 때문에).

+1

이런 상세한 답변을 가져 주셔서 감사합니다. – keeg

0

우리는 대신 RBAC의 컨트롤러 액션을 제한하는

AccessControlFilter

를 사용할 수 있습니다. 이 코드는 denyCallback 만 전달하는 경우 actionUpdate에 대한 액세스 권한을 부여합니다. 참고 https://github.com/yiisoft/yii2/blob/master/docs/guide/security-authorization.md

+0

모델을 먼저 찾은 다음 검사를 수행해야하지만 작업 전에 액세스 제어가 실행되어야합니다. 아니면 모델 찾기를위한 코드를 복제 할 수 있습니다. 또한 일반적인 예외가 아닌 HTTP 예외에 따라 던지는 것이 좋습니다. – arogachev