This commit is contained in:
hgc 2025-01-06 10:47:22 +08:00
parent 195a78ef16
commit d19edf4fd5
10 changed files with 814 additions and 1 deletions

88
app/middleware/JwtRpc.php Normal file
View File

@ -0,0 +1,88 @@
<?php
namespace app\middleware;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
use GRPC\Auth\AuthClient;
use GRPC\Auth\ValidateJwtTokenReq;
use GRPC\Auth\JwtVerifyResult;
class JwtRpc implements MiddlewareInterface
{
protected $authClient;
public function __construct()
{
// 初始化 AuthClient
$host = "192.168.21.27:22101"; // 替换为你的 Auth 服务地址
$this->authClient = new AuthClient($host);
}
public function process(Request $request, callable $handler): Response
{
// 从请求头中获取 JWT token
$jwtToken = $request->header('Authorization');
if (!$jwtToken) {
return response()->json(['error' => 'Authorization token is missing'], 401);
}
// 去除 Bearer 前缀
if (strpos($jwtToken, 'Bearer ') === 0) {
$jwtToken = substr($jwtToken, 7);
}
try {
// 创建 GRPC 请求
dump($jwtToken);
$grpcRequest = new ValidateJwtTokenReq();
$grpcRequest->setJwtToken($jwtToken);
// 调用 GRPC 服务
list($response, $status) = $this->authClient->ValidateJwtToken($grpcRequest)->wait();
if ($status->code !== \Grpc\STATUS_OK) {
return Json([
'code' => 1,
'msg' => 'GRPC service error',
'data' => []
]);
}
// 检查验证结果
if ($response->getResult() !== JwtVerifyResult::JWT_VERIFY_OK) {
return Json([
'code' => 1,
'msg' => 'Invalid token',
'data' => []
]);
}
// 将解析的 claims 数据传递给下层业务逻辑
$claims = $response->getClaims();
dump($claims);
return Json([
'code' => 0,
'msg' => 'test token well',
'data' => []
]);
$request->jwtClaims = $claims;
// if ($result['is_valid']) {
// dump("JWT 验证成功: " . json_encode($result['claims']));
// } else {
// dump("JWT 验证失败: " . $result['error']);
// }
// if (!$isValid) {
// return response()->json(['error' => 'Invalid token'], 401);
// }
// 如果验证通过,则继续处理请求
return $handler($request);
} catch (\Exception $e) {
return new Response(500, [], json_encode(['error' => 'Internal server error']));
}
}
}

View File

@ -43,7 +43,9 @@
"phpoffice/phpspreadsheet": "^3.6", "phpoffice/phpspreadsheet": "^3.6",
"grpc/grpc": "^1.38", "grpc/grpc": "^1.38",
"google/protobuf": "^4.29", "google/protobuf": "^4.29",
"firebase/php-jwt": "^6.10" "firebase/php-jwt": "^6.10",
"spiral/roadrunner-cli": "^2.6",
"spiral/roadrunner-grpc": "^3.4"
}, },
"suggest": { "suggest": {
"ext-event": "For better performance. " "ext-event": "For better performance. "
@ -53,6 +55,7 @@
"": "./", "": "./",
"app\\": "./app", "app\\": "./app",
"App\\": "./app", "App\\": "./app",
"GRPC\\": "generated/GRPC",
"app\\View\\Components\\": "./app/view/components" "app\\View\\Components\\": "./app/view/components"
} }
}, },

View File

@ -0,0 +1,59 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: proto/auth.proto
namespace GRPC\Auth;
use UnexpectedValueException;
/**
* 账户角色类型
*
* Protobuf type <code>auth.AccountRole</code>
*/
class AccountRole
{
/**
* Generated from protobuf enum <code>ACCOUNT_ROLE_UNSPECIFIED = 0;</code>
*/
const ACCOUNT_ROLE_UNSPECIFIED = 0;
/**
* 管理员
*
* Generated from protobuf enum <code>ACCOUNT_ROLE_MANAGER = 1;</code>
*/
const ACCOUNT_ROLE_MANAGER = 1;
/**
* 普通员工
*
* Generated from protobuf enum <code>ACCOUNT_ROLE_STAFF = 2;</code>
*/
const ACCOUNT_ROLE_STAFF = 2;
private static $valueToName = [
self::ACCOUNT_ROLE_UNSPECIFIED => 'ACCOUNT_ROLE_UNSPECIFIED',
self::ACCOUNT_ROLE_MANAGER => 'ACCOUNT_ROLE_MANAGER',
self::ACCOUNT_ROLE_STAFF => 'ACCOUNT_ROLE_STAFF',
];
public static function name($value)
{
if (!isset(self::$valueToName[$value])) {
throw new UnexpectedValueException(sprintf(
'Enum %s has no name defined for value %s', __CLASS__, $value));
}
return self::$valueToName[$value];
}
public static function value($name)
{
$const = __CLASS__ . '::' . strtoupper($name);
if (!defined($const)) {
throw new UnexpectedValueException(sprintf(
'Enum %s has no value defined for name %s', __CLASS__, $name));
}
return constant($const);
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace GRPC\Auth;
use Grpc\BaseStub;
use Grpc\UnaryCall;
use Grpc\Channel;
use Grpc\ChannelCredentials;
use GRPC\Auth\ValidateJwtTokenReq;
use GRPC\Auth\ValidateJwtTokenResp;
/**
* AuthClient 是通过手动实现的 GRPC 客户端类
*/
class AuthClient extends BaseStub
{
/**
* AuthClient 构造函数
*
* @param string $hostname 服务端地址(如 "192.168.21.27:22101"
* @param array $opts 客户端选项(可选)
* @param mixed $channel GRPC 通道(可选,默认使用明文连接)
*/
public function __construct(string $hostname, array $opts = [], $channel = null)
{
if ($channel === null) {
// 使用明文连接
$channel = new Channel($hostname, [
'credentials' => ChannelCredentials::createInsecure()
]);
}
parent::__construct($hostname, $opts, $channel);
}
/**
* 调用 ValidateJwtToken 方法
*
* @param ValidateJwtTokenReq $request 请求数据
* @param array $metadata 元数据(可选)
* @param array $options 调用选项(可选)
*
* @return ValidateJwtTokenResp
*/
public function ValidateJwtToken(
ValidateJwtTokenReq $request,
array $metadata = [],
array $options = []
): ValidateJwtTokenResp
{
try {
// 调试:输出请求数据
// dump('aaa',$request->getJwtToken());
// 调用 GRPC 服务
$unaryCall = $this->_simpleRequest(
'/auth.Auth/ValidateJwtToken', // 方法的完整路径
$request,
['\GRPC\Auth\ValidateJwtTokenResp', 'decode'], // 解码器
$metadata,
$options
);
// 使用 wait() 获取返回值
list($response, $status) = $unaryCall->wait();
// 调试:输出 GRPC 状态码
dump($status);
// 检查请求是否成功
if ($status->code !== \Grpc\STATUS_OK) {
throw new \Exception('GRPC call failed with status: ' . $status->details, $status->code);
}
// 返回解析后的响应数据
return $response;
} catch (\Exception $e) {
// 捕获异常并打印
dump($e->getMessage());
throw $e; // 继续抛出异常
}
}
}

View File

@ -0,0 +1,22 @@
<?php
# Generated by the protocol buffer compiler (roadrunner-server/grpc). DO NOT EDIT!
# source: proto/auth.proto
namespace GRPC\Auth;
use Spiral\RoadRunner\GRPC;
interface AuthInterface extends GRPC\ServiceInterface
{
// GRPC specific service name.
public const NAME = "auth.Auth";
/**
* @param GRPC\ContextInterface $ctx
* @param ValidateJwtTokenReq $in
* @return ValidateJwtTokenResp
*
* @throws GRPC\Exception\InvokeException
*/
public function ValidateJwtToken(GRPC\ContextInterface $ctx, ValidateJwtTokenReq $in): ValidateJwtTokenResp;
}

View File

@ -0,0 +1,269 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: proto/auth.proto
namespace GRPC\Auth;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>auth.JwtClaims</code>
*/
class JwtClaims extends \Google\Protobuf\Internal\Message
{
/**
* 所属应用
*
* Generated from protobuf field <code>string app = 1;</code>
*/
protected $app = '';
/**
* 用户id
*
* Generated from protobuf field <code>string uid = 2;</code>
*/
protected $uid = '';
/**
* 商户id
*
* Generated from protobuf field <code>string merchant_id = 3;</code>
*/
protected $merchant_id = '';
/**
* 用户在商户下的角色
*
* Generated from protobuf field <code>.auth.AccountRole role = 4;</code>
*/
protected $role = 0;
/**
* 过期时间戳
*
* Generated from protobuf field <code>int64 exp = 5;</code>
*/
protected $exp = 0;
/**
* 可刷新时间戳
*
* Generated from protobuf field <code>int64 refresh = 6;</code>
*/
protected $refresh = 0;
/**
* jwt token版本
*
* Generated from protobuf field <code>int64 ver = 7;</code>
*/
protected $ver = 0;
/**
* Constructor.
*
* @param array $data {
* Optional. Data for populating the Message object.
*
* @type string $app
* 所属应用
* @type string $uid
* 用户id
* @type string $merchant_id
* 商户id
* @type int $role
* 用户在商户下的角色
* @type int|string $exp
* 过期时间戳
* @type int|string $refresh
* 可刷新时间戳
* @type int|string $ver
* jwt token版本
* }
*/
public function __construct($data = NULL) {
\GRPC\GPBMetadata\Auth::initOnce();
parent::__construct($data);
}
/**
* 所属应用
*
* Generated from protobuf field <code>string app = 1;</code>
* @return string
*/
public function getApp()
{
return $this->app;
}
/**
* 所属应用
*
* Generated from protobuf field <code>string app = 1;</code>
* @param string $var
* @return $this
*/
public function setApp($var)
{
GPBUtil::checkString($var, True);
$this->app = $var;
return $this;
}
/**
* 用户id
*
* Generated from protobuf field <code>string uid = 2;</code>
* @return string
*/
public function getUid()
{
return $this->uid;
}
/**
* 用户id
*
* Generated from protobuf field <code>string uid = 2;</code>
* @param string $var
* @return $this
*/
public function setUid($var)
{
GPBUtil::checkString($var, True);
$this->uid = $var;
return $this;
}
/**
* 商户id
*
* Generated from protobuf field <code>string merchant_id = 3;</code>
* @return string
*/
public function getMerchantId()
{
return $this->merchant_id;
}
/**
* 商户id
*
* Generated from protobuf field <code>string merchant_id = 3;</code>
* @param string $var
* @return $this
*/
public function setMerchantId($var)
{
GPBUtil::checkString($var, True);
$this->merchant_id = $var;
return $this;
}
/**
* 用户在商户下的角色
*
* Generated from protobuf field <code>.auth.AccountRole role = 4;</code>
* @return int
*/
public function getRole()
{
return $this->role;
}
/**
* 用户在商户下的角色
*
* Generated from protobuf field <code>.auth.AccountRole role = 4;</code>
* @param int $var
* @return $this
*/
public function setRole($var)
{
GPBUtil::checkEnum($var, \GRPC\Auth\AccountRole::class);
$this->role = $var;
return $this;
}
/**
* 过期时间戳
*
* Generated from protobuf field <code>int64 exp = 5;</code>
* @return int|string
*/
public function getExp()
{
return $this->exp;
}
/**
* 过期时间戳
*
* Generated from protobuf field <code>int64 exp = 5;</code>
* @param int|string $var
* @return $this
*/
public function setExp($var)
{
GPBUtil::checkInt64($var);
$this->exp = $var;
return $this;
}
/**
* 可刷新时间戳
*
* Generated from protobuf field <code>int64 refresh = 6;</code>
* @return int|string
*/
public function getRefresh()
{
return $this->refresh;
}
/**
* 可刷新时间戳
*
* Generated from protobuf field <code>int64 refresh = 6;</code>
* @param int|string $var
* @return $this
*/
public function setRefresh($var)
{
GPBUtil::checkInt64($var);
$this->refresh = $var;
return $this;
}
/**
* jwt token版本
*
* Generated from protobuf field <code>int64 ver = 7;</code>
* @return int|string
*/
public function getVer()
{
return $this->ver;
}
/**
* jwt token版本
*
* Generated from protobuf field <code>int64 ver = 7;</code>
* @param int|string $var
* @return $this
*/
public function setVer($var)
{
GPBUtil::checkInt64($var);
$this->ver = $var;
return $this;
}
}

View File

@ -0,0 +1,87 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: proto/auth.proto
namespace GRPC\Auth;
use UnexpectedValueException;
/**
* jwt token验证结果
*
* Protobuf type <code>auth.JwtVerifyResult</code>
*/
class JwtVerifyResult
{
/**
* Generated from protobuf enum <code>JWT_VERIFY_UNSPECIFIED = 0;</code>
*/
const JWT_VERIFY_UNSPECIFIED = 0;
/**
* jwt 正常
*
* Generated from protobuf enum <code>JWT_VERIFY_OK = 1;</code>
*/
const JWT_VERIFY_OK = 1;
/**
* jwt 格式错误
*
* Generated from protobuf enum <code>JWT_VERIFY_BAD_FORMAT = 2;</code>
*/
const JWT_VERIFY_BAD_FORMAT = 2;
/**
* jwt 签名错误
*
* Generated from protobuf enum <code>JWT_VERIFY_SIGN_FAILED = 3;</code>
*/
const JWT_VERIFY_SIGN_FAILED = 3;
/**
* jwt 过期
*
* Generated from protobuf enum <code>JWT_VERIFY_EXPIRED = 4;</code>
*/
const JWT_VERIFY_EXPIRED = 4;
/**
* jwt 被撤销
*
* Generated from protobuf enum <code>JWT_VERIFY_REVOKED = 5;</code>
*/
const JWT_VERIFY_REVOKED = 5;
/**
* jwt 版本过低
*
* Generated from protobuf enum <code>JWT_VERSION_LOW = 6;</code>
*/
const JWT_VERSION_LOW = 6;
private static $valueToName = [
self::JWT_VERIFY_UNSPECIFIED => 'JWT_VERIFY_UNSPECIFIED',
self::JWT_VERIFY_OK => 'JWT_VERIFY_OK',
self::JWT_VERIFY_BAD_FORMAT => 'JWT_VERIFY_BAD_FORMAT',
self::JWT_VERIFY_SIGN_FAILED => 'JWT_VERIFY_SIGN_FAILED',
self::JWT_VERIFY_EXPIRED => 'JWT_VERIFY_EXPIRED',
self::JWT_VERIFY_REVOKED => 'JWT_VERIFY_REVOKED',
self::JWT_VERSION_LOW => 'JWT_VERSION_LOW',
];
public static function name($value)
{
if (!isset(self::$valueToName[$value])) {
throw new UnexpectedValueException(sprintf(
'Enum %s has no name defined for value %s', __CLASS__, $value));
}
return self::$valueToName[$value];
}
public static function value($name)
{
$const = __CLASS__ . '::' . strtoupper($name);
if (!defined($const)) {
throw new UnexpectedValueException(sprintf(
'Enum %s has no value defined for name %s', __CLASS__, $name));
}
return constant($const);
}
}

View File

@ -0,0 +1,58 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: proto/auth.proto
namespace GRPC\Auth;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>auth.ValidateJwtTokenReq</code>
*/
class ValidateJwtTokenReq extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>string jwt_token = 1;</code>
*/
protected $jwt_token = '';
/**
* Constructor.
*
* @param array $data {
* Optional. Data for populating the Message object.
*
* @type string $jwt_token
* }
*/
public function __construct($data = NULL) {
\GRPC\GPBMetadata\Auth::initOnce();
parent::__construct($data);
}
/**
* Generated from protobuf field <code>string jwt_token = 1;</code>
* @return string
*/
public function getJwtToken()
{
return $this->jwt_token;
}
/**
* Generated from protobuf field <code>string jwt_token = 1;</code>
* @param string $var
* @return $this
*/
public function setJwtToken($var)
{
GPBUtil::checkString($var, True);
$this->jwt_token = $var;
return $this;
}
}

View File

@ -0,0 +1,143 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: proto/auth.proto
namespace GRPC\Auth;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>auth.ValidateJwtTokenResp</code>
*/
class ValidateJwtTokenResp extends \Google\Protobuf\Internal\Message
{
/**
* 验证结果
*
* Generated from protobuf field <code>.auth.JwtVerifyResult result = 1;</code>
*/
protected $result = 0;
/**
* 换发的新token
*
* Generated from protobuf field <code>string new_token = 2;</code>
*/
protected $new_token = '';
/**
* jwt token解析出来的claims数据
*
* Generated from protobuf field <code>optional .auth.JwtClaims claims = 3;</code>
*/
protected $claims = null;
/**
* Constructor.
*
* @param array $data {
* Optional. Data for populating the Message object.
*
* @type int $result
* 验证结果
* @type string $new_token
* 换发的新token
* @type \GRPC\Auth\JwtClaims $claims
* jwt token解析出来的claims数据
* }
*/
public function __construct($data = NULL) {
\GRPC\GPBMetadata\Auth::initOnce();
parent::__construct($data);
}
/**
* 验证结果
*
* Generated from protobuf field <code>.auth.JwtVerifyResult result = 1;</code>
* @return int
*/
public function getResult()
{
return $this->result;
}
/**
* 验证结果
*
* Generated from protobuf field <code>.auth.JwtVerifyResult result = 1;</code>
* @param int $var
* @return $this
*/
public function setResult($var)
{
GPBUtil::checkEnum($var, \GRPC\Auth\JwtVerifyResult::class);
$this->result = $var;
return $this;
}
/**
* 换发的新token
*
* Generated from protobuf field <code>string new_token = 2;</code>
* @return string
*/
public function getNewToken()
{
return $this->new_token;
}
/**
* 换发的新token
*
* Generated from protobuf field <code>string new_token = 2;</code>
* @param string $var
* @return $this
*/
public function setNewToken($var)
{
GPBUtil::checkString($var, True);
$this->new_token = $var;
return $this;
}
/**
* jwt token解析出来的claims数据
*
* Generated from protobuf field <code>optional .auth.JwtClaims claims = 3;</code>
* @return \GRPC\Auth\JwtClaims|null
*/
public function getClaims()
{
return $this->claims;
}
public function hasClaims()
{
return isset($this->claims);
}
public function clearClaims()
{
unset($this->claims);
}
/**
* jwt token解析出来的claims数据
*
* Generated from protobuf field <code>optional .auth.JwtClaims claims = 3;</code>
* @param \GRPC\Auth\JwtClaims $var
* @return $this
*/
public function setClaims($var)
{
GPBUtil::checkMessage($var, \GRPC\Auth\JwtClaims::class);
$this->claims = $var;
return $this;
}
}

Binary file not shown.