Hyperf 完整项目-1-jwt 权限认证

1. 安装依赖

composer require phper666/jwt-auth

2.新建中间件

<?php
declare(strict_types=1);
namespace App\Middleware;
use Phper666\JwtAuth\Jwt;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Phper666\JwtAuth\Exception\TokenValidException;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
class JwtAuthMiddleware implements MiddlewareInterface
{
    /**
     * @var HttpResponse
     */

    protected $response;
    protected $prefix = 'Bearer';
    protected $jwt;

    public function __construct(HttpResponse $response, Jwt $jwt)
    {
        $this->response = $response;
        $this->jwt      = $jwt;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {

        $isValidToken = false;
        $token = $request->getHeader('Authorization')[0] ?? '';
        if (strlen($token) > 0) {
            $token = ucfirst($token);
            $arr   = explode($this->prefix . ' ', $token);
            $token = $arr[1] ?? '';
            try{
                if (strlen($token) > 0 && $this->jwt->checkToken()) {
                    $isValidToken = true;
                }
            }catch(\Exception $e){
                $data = [
                    'code' => 401,
                    'msg' => '对不起,token验证没有通过',
                    'data' => [],
                ];
                return $this->response->json($data);
            }
        }

        if ($isValidToken) {
            return $handler->handle($request);
        }
        $data = [
            'code' => 401,
            'msg' => '对不起,token验证没有通过',
            'data' => [],
        ];
        return $this->response->json($data);
    }
}

3.新建登录

<?php
declare(strict_types = 1);

namespace App\Controller\Auth;
use App\Model\User;
use Phper666\JwtAuth\Jwt;
use App\Controller\Controller;
use Hyperf\Di\Annotation\Inject;
class LoginController extends Controller
{
    /**
     * @Inject
     *
     * @var Jwt
     */
    protected $jwt;
    /**
     * 用户登录.
     *
     * @return array
     */
    public function login()
    {
        // $hash = password_hash($this->request->input('password'), PASSWORD_DEFAULT);
        // return $this->failed($hash);
        $user = User::query()->where('account', $this->request->input('account'))->first();
        //验证用户账户密码
        if (!empty($user->password) && password_verify($this->request->input('password'), $user->password)) {
            $userData = [
                'uid'       => $user->id,
                'account'  => $user->account,
            ];
            $token = $this->jwt->getToken($userData);
            $data  = [
                'token' => (string) $token,
                'exp'   => $this->jwt->getTTL(),
            ];
            return $this->success($data);
        }
        return $this->failed('登录失败');
    }
}

4.用户信息控制器

<?php
declare(strict_types=1);

namespace App\Controller;

use App\Model\User;
use Phper666\JwtAuth\Jwt;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Hyperf\Elasticsearch\ClientBuilderFactory;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Task\TaskExecutor;
use Hyperf\Utils\Coroutine;
use Hyperf\Task\Task;
use App\Task\MethodTask;
use Hyperf\Server\ServerFactory;

class UserController extends Controller
{

    /**
     * @Inject()
     * @var Jwt
     */
    protected $jwt;

    /**
     * @Inject()
     * @var ValidatorFactoryInterface
     */
    protected $validationFactory;

    /**
     * 获取用户信息
     * @return [type] [description]
     */
    public function info()
    {
        //获取token中的用户数据
        $user = $this->jwt->getParserData();
        $userInfo = User::query()->where('account', $user['account'])->get();

        return $this->success($userInfo);

    }

    /**
     * 用户退出
     * @return [type] [description]
     */
    public function logout()
    {
        if ($this->jwt->logout()) {
            return $this->success('','退出登录成功');
        };
        return $this->failed('退出登录失败');
    }

}

5.继承的控制器

<?php

declare(strict_types = 1);

namespace App\Controller;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerInterface;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
class Controller
{
    /**
     * @Inject
     *
     * @var ContainerInterface
     */
    protected $container;
    /**
     * @Inject
     *
     * @var RequestInterface
     */
    protected $request;
    /**
     * @Inject
     *
     * @var ResponseInterface
     */
    protected $response;
    /**
     * 请求成功
     *
     * @param        $data
     * @param string $message
     *
     * @return array
     */
    public function success($data, $message = 'success')
    {
        $code = $this->response->getStatusCode();
        return ['msg' => $message, 'code' => $code, 'data' => $data];
    }
    /**
     * 请求失败.
     *
     * @param string $message
     *
     * @return array
     */
    public function failed($message = 'Request format error!')
    {
        return ['msg' => $message, 'code' => 500, 'data' => ''];
    }
}

6.配置文件 config/autoload/jwt.php

<?php
declare(strict_types=1);
return [
    # 登录方式,sso为单点登录,mpop为多点登录
    'login_type' => env('JWT_LOGIN_TYPE', 'sso'),
    # 单点登录自定义数据中必须存在uid的键值,这个key你可以自行定义,只要自定义数据中存在该键即可
    'sso_key' => 'uid',
    # 非对称加密使用字符串,请使用自己加密的字符串
    'secret' => env('JWT_SECRET', 'phper666'),
    /*
     * JWT 权限keys
     * 对称算法: HS256, HS384 & HS512 使用 `JWT_SECRET`.
     * 非对称算法: RS256, RS384 & RS512 / ES256, ES384 & ES512 使用下面的公钥私钥.
     */
    'keys' => [
        # 公钥,例如:'file://path/to/public/key'
        'public' => env('JWT_PUBLIC_KEY'),
        # 私钥,例如:'file://path/to/private/key'
        'private' => env('JWT_PRIVATE_KEY'),
    ],
    # token过期时间,单位为秒
    'ttl' => env('JWT_TTL', 7200),
    # jwt的hearder加密算法
    'alg' => env('JWT_ALG', 'HS256'),
    # 是否开启黑名单,单点登录和多点登录的注销、刷新使原token失效,必须要开启黑名单,目前黑名单缓存只支持hyperf缓存驱动
    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
    # 黑名单的宽限时间 单位为:秒,注意:如果使用单点登录,该宽限时间无效
    'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),
    # 黑名单缓存token时间,注意:该时间一定要设置比token过期时间要大,默认为1天
    'blacklist_cache_ttl' => env('JWT_BLACKLIST_CACHE_TTL', 86400),
];

7. 创建路由

Router::post('/user/login', 'App\Controller\Auth\LoginController@login');
Router::post('/user/register', 'App\Controller\Auth\RegisterController@register');
//个人资料
Router::addGroup('/user/', function () {
    Router::get('info','App\Controller\UserController@info');
    Router::post('logout', 'App\Controller\UserController@logout');
    Router::get('elasticsearch', 'App\Controller\UserController@elasticsearch');
}, [
    'middleware' => [App\Middleware\JwtAuthMiddleware::class]
]);

接下来可以模拟API请求,看效果

jwt
讨论数量: 3

我的logout不生效 :cry:

1周前 评论
php迷途小书童 (楼主) 1周前

这个中间件其实不太需要,本身 phper666/jwt-auth 已经实现了

2天前 评论
php迷途小书童 (楼主) 2天前
hedeqiang (作者) 2天前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!