mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 16:22:49 +08:00
feat(api-key): add api_key table, source fields, model and auth middleware
This commit is contained in:
4
app/api/middleware.php
Normal file
4
app/api/middleware.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
|
||||
// API中间件通过控制器 $middleware 属性挂载,不需要全局注册
|
||||
return [];
|
||||
42
app/middleware/ApiKeyAuth.php
Normal file
42
app/middleware/ApiKeyAuth.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use app\model\ApiKey;
|
||||
|
||||
class ApiKeyAuth
|
||||
{
|
||||
public function handle($request, \Closure $next)
|
||||
{
|
||||
$raw_key = '';
|
||||
|
||||
// 优先从 Authorization: Bearer {key} 提取
|
||||
$authorization = $request->header('authorization', '');
|
||||
if (strpos($authorization, 'Bearer ') === 0) {
|
||||
$raw_key = substr($authorization, 7);
|
||||
}
|
||||
|
||||
// 若无 Bearer,尝试从 X-API-Key 请求头获取
|
||||
if (empty($raw_key)) {
|
||||
$raw_key = $request->header('x-api-key', '');
|
||||
}
|
||||
|
||||
if (empty($raw_key)) {
|
||||
return json(['code' => 401, 'msg' => '缺少 API Key', 'data' => null])->code(401);
|
||||
}
|
||||
|
||||
$api_key = ApiKey::verifyKey($raw_key);
|
||||
if (empty($api_key)) {
|
||||
return json(['code' => 401, 'msg' => 'API Key 无效或已禁用', 'data' => null])->code(401);
|
||||
}
|
||||
|
||||
// 注入权限到 Request
|
||||
$request->admin_id = $api_key->admin_id;
|
||||
$request->api_key_id = $api_key->id;
|
||||
$request->can_write_own = $api_key->can_write_own;
|
||||
$request->can_write_other = $api_key->can_write_other;
|
||||
$request->can_delete = $api_key->can_delete;
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
138
app/model/ApiKey.php
Normal file
138
app/model/ApiKey.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\common\model\Base;
|
||||
use think\model\concern\SoftDelete;
|
||||
|
||||
/**
|
||||
* @mixin think\Model
|
||||
*/
|
||||
class ApiKey extends Base
|
||||
{
|
||||
use SoftDelete;
|
||||
|
||||
protected $name = 'api_key';
|
||||
|
||||
protected $defaultSoftDelete = 0;
|
||||
|
||||
public function admin()
|
||||
{
|
||||
return $this->belongsTo(Admin::class, 'admin_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成API Key
|
||||
*
|
||||
* @param int $admin_id
|
||||
* @param string $name
|
||||
* @param int $can_write_own
|
||||
* @param int $can_write_other
|
||||
* @param int $can_delete
|
||||
*
|
||||
* @return string 明文Key,仅此一次返回
|
||||
*/
|
||||
public static function generateKey($admin_id, $name = '', $can_write_own = 0, $can_write_other = 0, $can_delete = 0)
|
||||
{
|
||||
$raw_key = 'ak_' . bin2hex(random_bytes(16));
|
||||
$hash = md5($raw_key);
|
||||
|
||||
self::create([
|
||||
'admin_id' => $admin_id,
|
||||
'name' => $name,
|
||||
'api_key' => $hash,
|
||||
'can_write_own' => $can_write_own,
|
||||
'can_write_other' => $can_write_other,
|
||||
'can_delete' => $can_delete,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
return $raw_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证API Key
|
||||
*
|
||||
* @param string $raw_key
|
||||
*
|
||||
* @return static|null
|
||||
*/
|
||||
public static function verifyKey($raw_key)
|
||||
{
|
||||
$hash = md5($raw_key);
|
||||
|
||||
return self::where('api_key', $hash)->where('status', 1)->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新生成Key
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return string 新的明文Key
|
||||
*/
|
||||
public static function regenerateKey($id)
|
||||
{
|
||||
$record = self::find($id);
|
||||
if (empty($record)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$raw_key = 'ak_' . bin2hex(random_bytes(16));
|
||||
$hash = md5($raw_key);
|
||||
|
||||
$record->api_key = $hash;
|
||||
$record->save();
|
||||
|
||||
return $raw_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可写自己的文章
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canWriteOwn()
|
||||
{
|
||||
return $this->can_write_own == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可写他人的文章
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canWriteOther()
|
||||
{
|
||||
return $this->can_write_other == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可删除
|
||||
* can_delete=0: 不可删除
|
||||
* can_delete=1: 仅API来源可删除
|
||||
* can_delete=2: 可删除
|
||||
*
|
||||
* @param string|null $source
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canDelete($source = null)
|
||||
{
|
||||
$can_delete = (int) $this->can_delete;
|
||||
|
||||
if ($can_delete === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($can_delete === 1) {
|
||||
return $source === 'api';
|
||||
}
|
||||
|
||||
if ($can_delete === 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user