本节主要讲解通过laravel 作为客户端调用go kratos 服务端,实现用户注册登录
环境
docker desk
laradock
laravel
环境准备
- 通过laradock php-fpm 安装 grpc protobuf
- workspace 安装protoc安装 protoc 与 grpc_php_plugin 可执行文件(这个plugin创建整很久)
- 为方便把grpc_php_plugin放到GRPC文件目录
- 在worksapce使用protoc 与 grpc_php_plugin 生成客户端代码
protoc --proto_path=./ --php_out=./php-src/ --grpc_out=./php-src/ --plugin=protoc-gen-grpc=./grpc_php_plugin ./api/user/v1/user.proto
生成客户端代码
实现
- 添加客户端调用服务层代码
- 添加grpc 调用组件及GRPC服务的自动加载
composer require grpc/grpc
composer require google/protobuf
grpc 服务文件自动加载
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"GPBMetadata\\":"GRPC/php-src/GPBMetadata/",
"":"GRPC/php-src/"
}
},
- 增加jwt 中间件
composer require firebase/php-jwt
添加中间件app/Http/Middleware/ApiJwt.php
<?php
namespace App\Http\Middleware;
use App\Service\Jwt;
use Closure;
use Illuminate\Http\Request;
class ApiJwt
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
//将token放入header中传输
$token = $request->header('Authorization');
if (!$token) {
return response()->json(['code' => 500, 'msg' => 'token不存在', 'data' => []]);
}
$result = Jwt::decodeToken($token);
if ($result) {
//将加密id解密传入下一步
$request->attributes->add(['user_id' => $result->user_id, 'nickname' => $result->nickname]);
} else {
return response()->json(['code' => 500, 'msg' => 'token过期', 'data' => []]);
}
return $next($request);
}
}
添加jwt 服务app/Service/Jwt.php
<?php
namespace App\Service;
use Firebase\JWT\JWT as JwtService;
use Firebase\JWT\Key;
class Jwt
{
protected static $key = 'laravel-tiway';
//加密
public static function createToken($userId, $nickname)
{
$payload = array(
"iss" => "http://example.org",
"aud" => "http://example.com",
'exp' => time() + (24 * 3600),
'user_id' => $userId,
'nickname' => $nickname,
);
$jwt = JwtService::encode($payload, self::$key, 'HS256');
return $jwt;
}
//解密
public static function decodeToken($jwt)
{
$decoded = JwtService::decode($jwt, new Key(self::$key, 'HS256'));
if ($decoded) {
return $decoded;
} else {
return false;
}
}
}
- 实现登录注册 app/Http/Controllers/UserController.php
<?php
namespace App\Http\Controllers;
use App\Service\GrpcUser;
use App\Service\Jwt;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* @param Request $request
* @return \Illuminate\Http\JsonResponse
* @throws \Exception
*/
public function register(Request $request)
{
$input = $request->only('nickname', 'mobile', 'password');
//用户手机号码是否已注册
$user = GrpcUser::getUserByMobile($input['mobile']);
if (isset($user['id'])) {
throw new \Exception('手机号码已被注册');
}
//创建用户
$user = GrpcUser::CreateUser($input['nickname'], $input['mobile'], $input['password']);
if (!isset($user['id'])) {
throw new \Exception('创建失败');
}
return response()->json([
'success' => true,
'data' => $user
], 200);
}
/**
* @param Request $request
* @return \Illuminate\Http\JsonResponse
* @throws \Exception
*/
public function login(Request $request)
{
$input = $request->only('mobile', 'password');
//是否已经存在相同手机号码
$isLogin = GrpcUser::checkoutUserPassword($input['mobile'], $input['password']);
if (!$isLogin) {
throw new \Exception('账号或密码错误');
}
//获取用户信息
$user = GrpcUser::getUserByMobile($input['mobile']);
//jwt
if (isset($user['id'])) {
$token = Jwt::createToken($user['id'], $user['nickname']);
}
return response()->json([
'success' => true,
'token' => $token,
]);
}
/**
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getUser(Request $request)
{
$userId = $request->attributes->get('user_id');
$user = GrpcUser::getUserById($userId);
return response()->json(['user' => $user]);
}
}
代码参考:laravel-tiway
总结
- 后期有时间把用户信息全部添加一个redis 缓存
- 简化controller,添加仓库层实现数据
- 如果你也是用docker desk,为求方便,联系我,我将提供workspace 和php-fpm 的镜像压缩包