swoft微服务实战三十八:网关主类增加token验证

6. 网关主类增加token验证:

(1). 增加token验证辅助函数:
app\Lib\TokenValidator.php:

namespace App\Lib;
use Firebase\JWT\JWT;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Context\Context;
use Swoft\Redis\Redis;
/**
 * @Bean(name="TokenValidator")
 */
class TokenValidator {
    public function checkToken(callable $callback)
    {
        // 规则暂定是url参数:url?token=xxx
        $getToken = Context::get()->getRequest()->get("token", "");
        if ($getToken == '') {
            throw new \Exception("token is not!");
        }
        // 返回的是一个对象,用array转换一下
        // array(1) {["username"] => string(6) "shenyi"}
        $token = (array)JWT::decode($getToken, 'abcde', ['HS256']);
        if (empty($token['username'])) {
            throw new \Exception("username is not!");
        }
        $key = 'token_' . $token['username'];
        if (empty(Redis::get($key)) || (Redis::get($key) !== $getToken)) {
            throw new \Exception("token is expired!");
        }
        // 先写上,后面会用到.把token值传出去,想办法传递用户身份信息到rpc服务中
        return $callback(['token' => $token]);
    }
}:. 验证逻辑:
   a. 先通过JWT来验证token,取出库里面的信息.
   b. 如果信息正确,去redis中去取出值进行比对.
   c. 如果不正确,代表这个过期了.

(2). 网关主类:
app\Http\main.php:

namespace App\Http;
use App\Lib\CustomizeRateLimiter;
use App\Lib\EnvConfig;
use App\Lib\ServiceHelper;
use App\Lib\ServiceSelector;
use App\Lib\TokenValidator;
use Swoft\Bean\Annotation\Mapping\Inject;
use Swoft\Bean\BeanFactory;
use Swoft\Http\Server\Annotation\Mapping\Controller;
use Swoft\Http\Server\Annotation\Mapping\RequestMapping;
use Swoft\Http\Server\Annotation\Mapping\RequestMethod;
/**
 * @Controller()
 */
class main {
    ...
    /**
     * @RequestMapping("/{prefix}/{service}/{method}", method={RequestMethod::POST, RequestMethod::OPTIONS})
     */
    public function test(string $prefix, string $service, string $method)
    {
        $param = jsonParams();
        try {
            $serviceList = $this->servicHelper->getService($this->envConfig->getServicePrefix() . "." . $prefix);
            $getService = $this->selector->selectByRoundRobin($serviceList);
            $host = "tcp://" . $getService['Address'] . ':' . $getService['Port'];
            $tags = $this->servicHelper->parseTags($getService);
            $callRpc = function () use ($host, $tags, $service, $method, $param){
                return requestRPC($host, choose($tags['NAMESPACE'], $this->envConfig->getNamespace()) . "\\".  $service, $method, $param);
            };
            // 是否需要验证jwt
            if (!empty($tags['tokenValid'][$service]) && in_array($method, $tags['tokenValid'][$service])) {
                /**
                 * @var TokenValidator $tokenValidator
                 */
                $tokenValidator = BeanFactory::getBean("TokenValidator");
                return $tokenValidator->checkToken($callRpc);
            }
            // 如果设置了限流,就执行限流函数,否则直接执行RPC目标调用
            if (!empty($tags['rateLimiter'])) {
                /**
                 * 下面方法没有提示,加这句
                 * @var CustomizeRateLimiter $rateLimiter
                 */
                $rateLimiter = BeanFactory::getBean("CustomizeRateLimiter");
                // 传前面两个参数的作用,主要是做日志记录
                $result = $rateLimiter->checkRate($service, $method, $callRpc, $tags['rateLimiter']);
            } else {
                $result = $callRpc();
            }
        } catch (\Exception $e) {
            $result = ["error" => $e->getMessage()];
        }
        return $result;
    }
}:. 访问POST:http://192.168.33.88:8306/course/ICourse/get?token=111,只有带token才能访问通过.. 问题:
   token验证通过后,直接返回了,怎么执行下一步的限流呢?   => 增加中间件处理
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值