是否建议在同一个Request类中编写插入/更新/删除授权代码?

时间:2016-03-16 11:59:13

标签: php laravel laravel-5.1 laravel-5.2

我在请求类中编写以下代码以进行验证和授权。所以下面的代码是添加/更新记录。

<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class UserRequest extends Request
{
    public function authorize()
    {
        return \Auth::user()->isAdmin();
    }

    public function rules()
    {
        return [
            'UserName' => 'required|max:50|min:3|unique:tbluser,UserName,' . 
                                                     \Request::get( 'UserID' ) . ',UserID',
        ];
    }
}

我的问题是:我应该编写代码来检查当前用户是否有权删除记录。为此我应该使用相同的Request类用于Add / Update或另一个专门用于删除身份验证的类?如果我使用相同的类,则将执行rules(),用于添加/更新

3 个答案:

答案 0 :(得分:2)

我将做的是以下内容:

<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class UserRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {

        switch ($this->method()) {

            // Show single record or multiple records
            case 'GET':
            default:
                return true;
            break;

            // Change a record
            case 'POST':
            case 'PUT':
            case 'PATCH':
            case 'DELETE':
               if(\Auth::user()->isAdmin()) {
                   return true;
               }
               return false;
            break;
        }
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        switch ($this->method()) {
            case 'GET':
            case 'DELETE':
                return [];
            break;

            case 'POST':
                return [
                    'UserName' => 'required|max:50|min:3|unique:tbluser,UserName'
                ];
            break;
            case 'PUT':
            case 'PATCH':

                return [
                    'UserName' => 'required|max:50|min:3|unique:tbluser,UserName,' . 
                                                                         \Request::get( 'UserID' ) . ',UserID',
                ];
            break;
            default:
            break;
        }
    }
}

对代码的更改是,在一个请求文件中,您可以根据使用的方法类型制定规则并更改授权。默认和get(显示用户或索引或类似的东西)不需要权限。对于所有其他方法(更改记录),用户必须是管理员。

答案 1 :(得分:2)

在我的Laravel应用程序authorize()中,请求方法只返回true。我在基本控制器类的特定方法中处理授权:

namespace App\Http\Controllers;

use Auth;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public function authorizeSameOwner($entity)
    {
        if (Auth::user()->is_admin) {
            return;
        }
        $this->authorize("same-owner", $entity);
    }
}

Controller的authorize()方法正在使用AuthServiceProvider中定义的功能执行实际授权。这就是我的情况:

namespace App\Providers;

use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
    ];

    /**
     * Register any application authentication / authorization services.
     *
     * @param  GateContract  $gate
     * @return void
     */
    public function boot(GateContract $gate)
    {
        $this->registerPolicies($gate);

        $gate->define("same-owner", function ($user, $entity) {
            if ($user->is_admin) {
                return true;
            }

            if (method_exists($entity, "getOwnerId")) {
                $ownerId = $entity->getOwnerId();
            } else {
                $ownerId = $entity->owner_id;
            }
            return $user->id === $ownerId;
        });
        $gate->define("same-user", function ($user, $entity) {
            return $user->is_admin || $user->id === $entity->id;
        });
    }
}

以下是实际资源控制器方法的样子:

/**
 * Update the specified resource in storage.
 *
 * @param  StayRequest  $request
 * @param  Stay $stay
 * @return Response
 */
public function update(StayRequest $request, Stay $stay)
{
    $this->authorizeSameOwner($stay);

    $stay->update($request->all());

    return redirect()->route("stays.index");
}

/**
 * Remove the specified resource from storage.
 *
 * @param  Stay $stay
 * @return Response
 */
public function destroy(Stay $stay)
{
    $this->authorizeSameOwner($stay);

    $stay->delete();

    return redirect()->route("stays.index");
}

答案 2 :(得分:2)

我认为这实际上取决于你的建筑。如果你正在创建一个只有几个限制区域的小应用程序,那么你可以轻松地处理这个问题。

但是,如果您的禁区很大,我认为您应该使用Laravel政策,这将提供更多的控制权,并在他们自己的课程中保持更有条理。

关于如何拆分Request类我认为任何请求动词的类都是完全正确的。它非常常见,您可以使用CreateUserRequest进行创建和更新,但是删除可能有不同的规则,因为检查记录确实存在或检查删除验证复选框已选中...只需为其规则创建一个不同的类。

如果您认为某些操作可以由同一规则授权(在本例中为isAdmin),您还可以创建一个抽象的AdminRequest来处理此授权。同样,如果系统根本不复杂。