安全
认证
Orion 目前不提供任何认证功能,认证能力的搭建由开发者自行负责。我们推荐使用 Laravel Passport 或 Laravel Sanctum 来实现这一目的。
授权
模型控制器和关联控制器都依赖模型策略来判断当前认证用户是否被允许执行某些操作。
虽然不建议这样做,但在某些情况下,你可能希望在特定控制器上禁用授权检查。为此,可以使用 Orion\Concerns\DisableAuthorization trait。
<?php
namespace App\Http\Controllers\Api;
use App\Models\Post;
use Orion\Concerns\DisableAuthorization;
class PostsController extends ApiController
{
use DisableAuthorization;
/**
* @var string $model
*/
protected $model = Post::class;
}
配合 Sanctum(或其他自定义 Auth guard)使用
默认情况下,授权时使用 api guard 来解析当前认证用户。
不过,你可以通过在 config/orion.php 中设置 auth.guard,或在控制器上重写 resolveUser 方法,来改变用户的解析方式。
<?php
namespace App\Http\Controllers\Api;
use App\Models\Post;
class PostsController extends ApiController
{
/**
* @var string $model
*/
protected $model = Post::class;
/**
* 基于守卫(guard)获取当前已认证的用户。
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function resolveUser()
{
return Auth::guard('sanctum')->user();
}
}
授权父实体
关联操作会向策略传递一个额外参数——父实体。你可以利用该参数设置额外的检查,判断用户是否被授权在给定父实体的上下文中对关联实体执行某些操作。
class PostPolicy
{
public function update($user, $post)
{
return $post->user_id === $user->id;
}
}
class PostMetaPolicy
{
public function update($user, $postMeta, $post) // <---- 这里的 $post 是父实体
{
// 请注意,此检查是针对父实体 $post 执行的,
// 而不是关联实体 $postMeta
return Gate::forUser($user)->inspect('update', $post);
}
public function create($user, $post)
{
return Gate::forUser($user)->inspect('update', $post);
}
}
自定义策略类
同一模型在不同控制器或场景中使用不同的授权规则是很常见的。默认情况下,策略由 Laravel 通过其内置机制解析。不过,如果你希望为某个控制器使用特定的策略,请相应地设置 protected $policy 或 protected $parentPolicy 变量:
模型控制器
<?php
namespace App\Http\Controllers\Api;
use App\Models\Post;
use App\Policies\CustomPostPolicy;
class PostsController extends ApiController
{
/**
* @var string $model
*/
protected $model = Post::class;
/**
* @var string $policy
*/
protected $policy = CustomPostPolicy::class;
}
关联控制器
<?php
namespace App\Http\Controllers\Api;
use App\Models\Team;
use App\Policies\CustomPostPolicy;
use App\Policies\CustomTeamPolicy;
use Orion\Http\Controllers\RelationController;
class TeamPostsController extends RelationController
{
/**
* @var string $model
*/
protected $model = Team::class; // 或 "App\Models\Team"
/**
* 在 Post 模型上定义的关联名称
*/
protected $relation = 'posts';
/**
* @var string $parentPolicy
*/
protected $parentPolicy = CustomTeamPolicy::class;
/**
* @var string $policy
*/
protected $policy = CustomPostPolicy::class;
}
验证
Orion\Http\Requests\Request 类,而不是 Illuminate\Foundation\Http\FormRequest。为了验证发送到 store 和 update 端点的请求数据,Orion 会按照类名模式 App\Http\Requests\<model>Request 查找资源模型对应的请求类。
例如,如果你有一个 App\Models\Message 模型,对应的请求类就是 App\Http\Requests\MessageRequest。
如果你的应用中请求类的命名不遵循这一约定,或者你只是想更明确地指定,可以将控制器上的 protected $request 属性设置为请求类的完全限定类名。
<?php
namespace App\Http\Controllers\Api;
use App\Models\Message;
use App\Http\Requests\CustomMessageRequest;
class MessagesController extends ApiController
{
/**
* @var string $model
*/
protected $model = Message::class;
/**
* @var string $request
*/
protected $request = CustomMessageRequest::class;
}
随后,请求类会通过 Laravel 的服务容器进行绑定,并在 store 和 update 方法中用于验证请求数据,效果与在方法签名中显式声明完全相同:
public function store(CustomMessageRequest $request)
{
...
}
验证规则
为 store 和 update 操作定义规则
Orion 提供了 Orion\Http\Requests\Request 类,其中包含一系列用于指定验证规则的方法。
要为 store 和 update 两个端点定义共用规则,可以使用 commonRules 方法。
如果你想定义特定于某个端点的规则,可以使用 storeRules 和 updateRules 方法。
storeRules 和 updateRules 方法与 commonRules 方法中包含相同的键,则前者中为该字段指定的规则会覆盖 commonRules 方法中的规则。<?php
namespace App\Http\Requests;
use Orion\Http\Requests\Request;
class PostRequest extends Request
{
public function commonRules() : array
{
return [
'title' => 'required'
];
}
public function storeRules() : array
{
return [
'status' => 'required|in:draft,review'
];
}
}
在这个示例中,当请求发送到 store 端点时,title 和 status 两个字段都是必填的。而当请求发送到 update 端点时,只有 title 字段是必填的,因为 updateRules 方法中没有定义其他规则,而 title 字段在 commonRules 方法中被标记为必填。
为关联专属操作定义规则
你还可以为关联专属端点定义规则:associateRules、attachRules、detachRules、syncRules、toggleRules、updatePivotRules。
commonRules 方法中的规则合并。为批量操作定义规则
你还可以为批量端点定义规则:batchStoreRules、batchUpdateRules。
验证消息
就像可以为特定端点配置规则一样,也可以自定义它们的验证消息。
为 store 和 update 操作自定义验证消息
要为 store 和 update 两个端点定义共用消息,可以使用 commonMessages 方法。
如果你想定义特定于某个端点的消息,可以使用 storeMessages 和 updateMessages 方法。
storeMessages 和 updateMessages 方法与 commonMessages 方法中包含相同的键,则前者中为该字段指定的消息会覆盖 commonMessages 方法中的消息。为关联专属操作自定义验证消息
你还可以为关联专属端点自定义消息:associateMessages、attachMessages、detachMessages、syncMessages、toggleMessages、updatePivotMessages。
commonMessages 方法中的消息合并。为批量操作自定义验证消息
你还可以为批量端点自定义消息:batchStoreMessages、batchUpdateMessages。
获取请求数据
默认情况下,在存储或更新实体时,会获取全部请求数据并传入模型的 fill 方法。
不过,也可以只传入已验证的数据。为此,请在 orion.php 配置文件中将 use_validated 设置为 true。