Featured image of post 在 PHP 后台 dcat-admin 中使用 grpc 客户端登录系统

在 PHP 后台 dcat-admin 中使用 grpc 客户端登录系统

grpc client

前言

  • 公司用go-zero弄了一个统一账号中心服务
  • 部分项目的后台用dcat-admin搭建后台, 也去调用账号中心的用户去登录, 记录一下过程

环境依赖

代码

  • 重写登录验证控制器
<?php

namespace App\Admin\Controllers;

use App\Services\AccountRpc;
use Dcat\Admin\Admin;
use Dcat\Admin\Http\Controllers\AuthController as BaseAuthController;
use Dcat\Admin\Models\Administrator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;

class AuthController extends BaseAuthController
{
    public function postLogin(Request $request)
    {
        $username = $request->input('username');
        $password = $request->input('password');
        $remember = (bool)$request->input('remember', false);

        $admin = Administrator::query()->firstOrNew([
            'username' => $username
        ]);
        
        // 用户已经存在, 去查找密码
        if ($admin->exists) {
            // 检查密码
            if (!Hash::check($password, $admin->password)) {
                return $this->validationErrorsResponse([
                    $this->username() => '密码错误',
                ]);
            }

            // 查看 token 是否还有效
            try {
                // 可以获取到信息, 那么直接登录
                $res = AccountRpc::me($admin->remember_token);
                $this->guard()->login($admin, $remember);

                return $this->sendLoginResponse($request);

            } catch (\Exception $e) {
                Log::error($e);
            }
        }

        try {
            $res = AccountRpc::login($username, $password);
        } catch (\Exception $e) {
            return $this->validationErrorsResponse([
                $this->username() => 'rpc:' . $e->getMessage(),
            ]);
        }

        // 如果这个用户没有, 那么就去创建管理员
        $admin->name = $res->getUser()->getNickname();
        $admin->password = Hash::make($password);
        $admin->remember_token = $res->getSession()->getToken();
        $admin->save();

        $this->guard()->login($admin, $remember);

        return $this->sendLoginResponse($request);
    }

    public function getLogout(Request $request)
    {
        $admin = $this->guard()->user();

        try {
            // rpc 调用
            AccountRpc::logout($admin->remember_token);
        } catch (\Exception $e) {
            Log::error($e->getMessage());
        }

        $this->guard()->logout();

        $request->session()->invalidate();

        $path = admin_url('auth/login');
        if ($request->pjax()) {
            return "<script>location.href = '$path';</script>";
        }

        return redirect($path);
    }
}
  • 账号中心服务类的代码(注意设置超时时间)
<?php


namespace App\Services;

use Account\AccountClient;
use ReflectionClass;

class AccountRpc
{
    protected static $client;

    public static function login($username, $password)
    {
         $meta = [
            'appId' => ['test'], 
            'groupId' => ['test'], 
        ];
        // 注意设置超时时间
        list($res, $status) = self::client()->Auth(new AuthRequest(), $meta, ['timeout' => 3 * 1000 * 1000])->wait();

        if ($status->code !== 0) {
            throw new \Exception($status->details);
        }

        return $res;
    }

    public static function me($token){}

    public static function logout($token){}

    public static function client()
    {
        if (is_null(self::$client)) {
            self::$client = new AccountClient(config('rpc.account'), [
                'credentials' => \Grpc\ChannelCredentials::createInsecure(),
            ]);
        }

        return self::$client;
    }
}

问题

  • 代码在本地运行起来是没问题, 但是部署到测试环境发现rpc请求会阻塞, 然后查了一下才知道grpc扩展和swoole扩展有冲突https://github.com/hhxsv5/laravel-s/issues/281
  • 由于我使用的是laravel-s, 所以也有相同的问题, 解决方法在Dockerfile文件加以下配置
### ... 在 install grpc 后面加
RUN install-php-extensions pcntl redis pdo_mysql zip bcmath gd grpc

RUN echo "grpc.enable_fork_support = 1" >> /usr/local/etc/php/conf.d/docker-php-ext-grpc.ini &&\
    echo "grpc.poll_strategy = epoll1" >> /usr/local/etc/php/conf.d/docker-php-ext-grpc.ini