sinbadxiii / phalcon-auth-jwt
基本的Phalcon JWT认证
Requires
- php: ^7.4 || ^8.1
- ext-phalcon: ^5.0
- lcobucci/jwt: ^4.0
- nesbot/carbon: ^2.0
- sinbadxiii/phalcon-auth: ^v2.0.0
Requires (Dev)
- mockery/mockery: ^1.4
- phpunit/phpunit: ^9.5
This package is auto-updated.
Last update: 2024-09-15 12:38:40 UTC
README
示例微应用 sinbadxiii/phalcon-auth-jwt-example
Phalcon认证库的附加JWT保护 sinbadxiii/phalcon-auth
演示
需求
Phalcon: ^5
PHP: ^7.4 || ^8.1
安装
通过composer安装
运行以下命令以获取最新版本:
composer require "sinbadxiii/phalcon-auth-jwt"
添加服务提供者
use Sinbadxiii\PhalconAuthJWT\Blacklist; use Sinbadxiii\PhalconAuthJWT\Builder; use Sinbadxiii\PhalconAuthJWT\Http\Parser\Chains\AuthHeaders; use Sinbadxiii\PhalconAuthJWT\Http\Parser\Chains\InputSource; use Sinbadxiii\PhalconAuthJWT\Http\Parser\Chains\QueryString; use Sinbadxiii\PhalconAuthJWT\Http\Parser\Parser; use Sinbadxiii\PhalconAuthJWT\JWT; use Sinbadxiii\PhalconAuthJWT\Manager as JWTManager; $di->setShared("jwt", function () { $configJwt = $this->getConfig()->path('jwt'); $providerJwt = $configJwt->providers->jwt; $builder = new Builder(); $builder->lockSubject($configJwt->lock_subject) ->setTTL($configJwt->ttl) ->setRequiredClaims($configJwt->required_claims->toArray()) ->setLeeway($configJwt->leeway) ->setMaxRefreshPeriod($configJwt->max_refresh_period); $parser = new Parser($this->getRequest(), [ new AuthHeaders, new QueryString, new InputSource, ]); $providerStorage = $configJwt->providers->storage; $blacklist = new Blacklist(new $providerStorage($this->getCache())); $blacklist->setGracePeriod($configJwt->blacklist_grace_period); $manager = new JWTManager(new $providerJwt( $configJwt->secret, $configJwt->algo, $configJwt->keys->toArray() ), $blacklist, $builder); $manager->setBlacklistEnabled((bool) $configJwt->blacklist_enabled); return new JWT($builder, $manager, $parser); });
配置
将config文件夹中的config/jwt.php文件复制到您的文件夹并合并配置
生成密钥
在config jwt.php中更新secret
值或在您的.env文件中更新JWT_SECRET值。
生成一个32字符的密钥短语,例如这里 https://passwordsgenerator.net/
更新您的用户模型
首先您需要在您的用户模型上实现Sinbadxiii\PhalconAuthJWT\JWTSubject接口,这需要您实现getJWTIdentifier()
和getJWTCustomClaims()
方法。
以下是一个例子
<?php namespace App\Models; use Phalcon\Mvc\Model; use Sinbadxiii\PhalconAuthJWT\JWTSubject; class User extends Model implements JWTSubject { //... public function getJWTIdentifier() { return $this->id; } public function getJWTCustomClaims() { return [ "email" => $this->email, "username" => $this->username ]; } }
创建认证访问,例如"jwt"
<?php namespace App\Security\Access; use Sinbadxiii\PhalconAuth\Access\AbstractAccess; class Jwt extends AbstractAccess { /** * @return bool */ public function allowedIf(): bool { return $this->auth->parseToken()->check(); } }
设置为JWT保护
$di->setShared("auth", function () { $security = $this->getSecurity(); $adapter = new \Sinbadxiii\PhalconAuth\Adapter\Model($security); $adapter->setModel(App\Models\User::class); $guard = new \Sinbadxiii\PhalconAuthJWT\Guard\JWTGuard( $adapter, $this->getJwt(), $this->getRequest(), $this->getEventsManager(), ); $manager = new Manager(); $manager->addGuard("jwt", $guard); $manager->setDefaultGuard($guard); $manager->setAccess(new \App\Security\Access\Jwt()); $manager->except("/auth/login"); return $manager; });
这里我们告诉api
保护使用jwt
驱动程序,并将api保护设置为默认。
现在我们可以使用带有JWT保护的Phalcon Auth了。
添加一些基本处理器
$application = new \Phalcon\Mvc\Micro($di); $eventsManager = new Manager(); $application->post( "/auth/logout", function () { $this->auth->logout(); return ['message' => 'Successfully logged out']; } ); $application->post( "/auth/refresh", function () { $token = $this->auth->refresh(); return $token->toResponse(); } ); $application->post( '/auth/login', function () { $credentials = [ 'email' => $this->request->getJsonRawBody()->email, 'password' => $this->request->getJsonRawBody()->password ]; $this->auth->claims(['aud' => [ $this->request->getURI() ]]); if (! $token = $this->auth->attempt($credentials)) { return ['error' => 'Unauthorized']; } return $token->toResponse(); } ); $application->get( '/', function () { return [ 'message' => 'hello, my friend' ]; } );
示例认证登录控制器
<?php declare(strict_types=1); namespace App\Controllers\Auth; use Phalcon\Mvc\Controller; class LoginController extends Controller { public function loginAction() { $credentials = [ 'email' => $this->request->getJsonRawBody()->email, 'password' => $this->request->getJsonRawBody()->password ]; $this->auth->claims(['aud' => [ $this->request->getURI() ]]); if (! $token = $this->auth->attempt($credentials)) { $this->response->setJsonContent(['error' => 'Unauthorized'])->send(); } return $this->respondWithToken($token); } public function meAction() { $this->response->setJsonContent($this->auth->user())->send(); } public function logoutAction() { $this->auth->logout(); $this->response->setJsonContent(['message' => 'Successfully logged out'])->send(); } public function refreshAction() { return $this->respondWithToken($this->auth->refresh()); } protected function respondWithToken($token) { $this->response->setJsonContent($token->toResponse())->send(); } }
附加中间件
中间件的示例代码
<?php namespace App\Middlewares; use Phalcon\Mvc\Micro\MiddlewareInterface; use Phalcon\Mvc\Micro; use function in_array; class AuthMiddleware implements MiddlewareInterface { public function call(Micro $application) { $authService = $application->getDI()->get("auth"); if ($access = $authService->getAccess()) { $excepts = $access->getExceptActions(); $uri = $application->getDI()->get("request")->getURI(true); if (!in_array($uri, $excepts)) { try { $authService->parseToken()->checkOrFail(); } catch (\Throwable $t) { $responseService = $application->getDI()->get("response"); $responseService->setStatusCode(401, 'Unauthorized'); $responseService->setJsonContent( [ "error" => "Unauthorized: " . $t->getMessage(), "code" => 401 ] ); if (!$responseService->isSent()) { $responseService->send(); } } } } return true; } }
并附加
$application = new \Phalcon\Mvc\Micro($di); $eventsManager = new Manager(); $eventsManager->attach('micro', new AuthMiddleware()); $application->before(new AuthMiddleware());
现在您应该能够使用一些有效凭证POST到登录端点(例如http://0.0.0.0:8000/auth/login),并看到以下响应
{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJhdWQiOlsiXC9hdXRoXC9sb2dpbiJdLCJleHAiOjE2MzE2OTkwOTMsImlzcyI6IjAuMC4wLjA6ODAwMCIsImlhdCI6MTYzMTY5NzI5MywianRpIjoiZFNhaGhyeUciLCJzdWIiOiIzIiwiZW1haWwiOiIxMjM0NUAxMjM0NS5ydSIsInVzZXJuYW1lIjoiMTIzNDUgdXNlcm5hbWUifQ.bTyngpVQt86IwtySdRUxPgZH_xk-44hYHTkmiA3BC_0s75TvkuLqTC9WN1jzBIR7Q_H4dWb_ErPR2MlTaw9VQA", "token_type": "bearer", "expires_in": 1800 }
有几种方法可以通过http发送令牌
授权头
Authorization Bearer eyJ0eXAiOiJKV1QiLC...
查询字符串参数
http://0.0.0.0:8000/me?token=eyJ0eXAiOiJKV1QiLC...
异常
方法
多个保护
$credentials = ['email' => 'eaxample@gmail.com', 'password' => '1234']; $token = $this->auth->guard('api')->attempt($credentials);
attempt()
尝试使用某些凭据认证用户。
// Generate a token for the user if the credentials are valid $token = $this->auth->attempt($credentials);
这将返回一个jwt或null
login()
登录用户并为他们返回一个jwt。
// Get some user from somewhere $user = User::findFirst(1); // Get the token $token = $this->auth->login($user);
user()
获取当前认证的用户。
// Get the currently authenticated user $user = $this->auth->user();
如果用户未认证,则返回null。
logout()
注销用户 - 这将使当前令牌无效并取消设置认证用户。
$this->auth->logout();
refresh()
刷新令牌,使当前令牌无效
$newToken = $this->auth->refresh();
invalidate()
使令牌无效(将其添加到黑名单)
$this->auth->invalidate();
tokenById()
根据给定的用户ID获取令牌。
$token = $this->auth->tokenById(1);
payload()
获取原始JWT负载
$payload = $this->auth->payload(); // then you can access the claims directly e.g. $payload->get('sub'); // = 1 $payload['jti']; // = 'sFF32fsDfs' $payload('exp') // = 1665544846 $payload->toArray(); // = ['sub' => 1, 'exp' => 1665544846, 'jti' => 'sFF32fsDfs'] etc
validate()
验证用户的凭据
if ($this->auth->validate($credentials)) { // credentials are valid }
更高级的使用
添加自定义声明
$token = $this->auth->claims(['username' => 'phalconist'])->attempt($credentials);
显式设置令牌
$user = $this->auth->setToken('eyJhb...')->user();
检查令牌
检查令牌的正确性
$this->auth->parseToken()->checkOrFail()
如果没有问题,将返回true
或抛出异常
- Sinbadxiii\PhalconAuthJWT\Exceptions\TokenExpiredException ('令牌已过期')
- Sinbadxiii\PhalconAuthJWT\Exceptions\TokenBlacklistedException ('令牌已被列入黑名单')
- Sinbadxiii\PhalconAuthJWT\Exceptions\TokenInvalidException
许可证
MIT许可(MIT)。请参阅许可文件以获取更多信息。