From 83ce55f2132a7a49c917ceb5f5c64fbd4693b612 Mon Sep 17 00:00:00 2001 From: ott321 Date: Sun, 20 May 2018 23:50:48 +0800 Subject: [PATCH 01/24] =?UTF-8?q?=E5=A4=A7=E4=BD=93=E5=AE=8C=E5=96=84,?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=B5=8B=E8=AF=95=E5=90=8E=E7=BB=AD=E8=A1=A5?= =?UTF-8?q?=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 12 ++ .php_cs | 38 ++++ .travis.yml | 20 ++ README.md | 30 +++ composer.json | 39 ++++ phpunit.xml | 21 ++ src/AuthManager.php | 217 ++++++++++++++++++++ src/Bean/AuthResult.php | 63 ++++++ src/Bean/AuthSession.php | 161 +++++++++++++++ src/Bootstrap/CoreBean.php | 38 ++++ src/Constants/AuthConstants.php | 28 +++ src/Exception/AuthException.php | 23 +++ src/Helper/ErrorCode.php | 55 +++++ src/Helper/ErrorCodeHelper.php | 135 ++++++++++++ src/Mapping/AccountTypeInterface.php | 37 ++++ src/Mapping/AuthHandleInterface.php | 22 ++ src/Middleware/AuthMiddleware.php | 39 ++++ src/Parser/AuthorizationHeaderParser.php | 76 +++++++ src/Parser/AuthorizationParserInterface.php | 20 ++ src/Parser/BasicAuthParser.php | 58 ++++++ src/Parser/BearerTokenParser.php | 54 +++++ src/Parser/JWTTokenParser.php | 141 +++++++++++++ src/Parser/TokenParserInterface.php | 30 +++ test/.env | 50 +++++ test/bootstrap.php | 30 +++ test/config/beans/base.php | 3 + test/config/beans/log.php | 33 +++ test/config/define.php | 26 +++ test/config/properties/app.php | 21 ++ test/config/properties/cache.php | 17 ++ test/config/server.php | 37 ++++ 31 files changed, 1574 insertions(+) create mode 100644 .gitignore create mode 100644 .php_cs create mode 100644 .travis.yml create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml create mode 100644 src/AuthManager.php create mode 100644 src/Bean/AuthResult.php create mode 100644 src/Bean/AuthSession.php create mode 100644 src/Bootstrap/CoreBean.php create mode 100644 src/Constants/AuthConstants.php create mode 100644 src/Exception/AuthException.php create mode 100644 src/Helper/ErrorCode.php create mode 100644 src/Helper/ErrorCodeHelper.php create mode 100644 src/Mapping/AccountTypeInterface.php create mode 100644 src/Mapping/AuthHandleInterface.php create mode 100644 src/Middleware/AuthMiddleware.php create mode 100644 src/Parser/AuthorizationHeaderParser.php create mode 100644 src/Parser/AuthorizationParserInterface.php create mode 100644 src/Parser/BasicAuthParser.php create mode 100644 src/Parser/BearerTokenParser.php create mode 100644 src/Parser/JWTTokenParser.php create mode 100644 src/Parser/TokenParserInterface.php create mode 100644 test/.env create mode 100644 test/bootstrap.php create mode 100644 test/config/beans/base.php create mode 100644 test/config/beans/log.php create mode 100644 test/config/define.php create mode 100644 test/config/properties/app.php create mode 100644 test/config/properties/cache.php create mode 100644 test/config/server.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6156e88 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.buildpath +.settings/ +.project +*.patch +.idea/ +.git/ +runtime/ +vendor/ +temp/ +*.lock +.phpintel/ +.DS_Store \ No newline at end of file diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..41e1b73 --- /dev/null +++ b/.php_cs @@ -0,0 +1,38 @@ +setRiskyAllowed(true) + ->setRules([ + '@PSR2' => true, + 'header_comment' => [ + 'commentType' => 'PHPDoc', + 'header' => $header, + 'separate' => 'none' + ], + 'array_syntax' => [ + 'syntax' => 'short' + ], + 'single_quote' => true, + 'class_attributes_separation' => true, + 'no_unused_imports' => true, + 'standardize_not_equals' => true, + ]) + ->setFinder( + PhpCsFixer\Finder::create() + ->exclude('public') + ->exclude('resources') + ->exclude('config') + ->exclude('runtime') + ->exclude('vendor') + ->in(__DIR__) + ) + ->setUsingCache(false); diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e12681e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: php + +php: + - 7.0 + - 7.1 + +services: + - mysql + +before_install: + - mysql -e 'CREATE DATABASE IF NOT EXISTS test;' + +install: + - wget https://github.com/redis/hiredis/archive/v0.13.3.tar.gz -O hiredis.tar.gz && mkdir -p hiredis && tar -xf hiredis.tar.gz -C hiredis --strip-components=1 && cd hiredis && sudo make -j$(nproc) && sudo make install && sudo ldconfig && cd .. + - pecl install -f swoole-2.0.12 + +before_script: + - composer update + +script: composer test diff --git a/README.md b/README.md new file mode 100644 index 0000000..a36abe5 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# Swoft Auth + +Swoft Auth Component + +## Install + +- composer command + +```bash +composer require swoft/auth +``` + +## Document + +```php + +稍后再补... + + +``` + +## Unit testing + +```bash +phpunit +``` + +## LICENSE + +The Component is open-sourced software licensed under the [Apache license](LICENSE). diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..92cca52 --- /dev/null +++ b/composer.json @@ -0,0 +1,39 @@ +{ + "name": "swoft/auth", + "type": "library", + "keywords": [ + "php", + "swoole", + "swoft" + ], + "description": "microservice framework base on swoole", + "license": "Apache-2.0", + "require": { + "swoft/http-server": "^1.0", + "firebase/php-jwt": "^5.0", + "psr/simple-cache": "^1.0" + }, + "autoload": { + "psr-4": { + "Swoft\\Auth\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "SwoftTest\\Auth\\": "test/Cases" + } + }, + "repositories": [ + { + "type": "composer", + "url": "https://packagist.phpcomposer.com" + } + ], + "require-dev": { + "eaglewu/swoole-ide-helper": "dev-master", + "phpunit/phpunit": "^5.7" + }, + "scripts": { + "test": "./vendor/bin/phpunit -c phpunit.xml" + } +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..b259449 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,21 @@ + + + + + ./test/Cases + + + + + ./app + + + diff --git a/src/AuthManager.php b/src/AuthManager.php new file mode 100644 index 0000000..d118587 --- /dev/null +++ b/src/AuthManager.php @@ -0,0 +1,217 @@ + + */ + +namespace Swoft\Auth; + +use App\Component\Auth\Account\AccountTypeInterface; +use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\InvalidArgumentException; +use Swoft\App; +use Swoft\Auth\Bean\AuthResult; +use Swoft\Auth\Bean\AuthSession; +use Swoft\Auth\Exception\AuthException; +use Swoft\Auth\Helper\ErrorCode; +use Swoft\Auth\Parser\TokenParserInterface; +use Swoft\Bean\Annotation\Value; +use Swoft\Core\RequestContext; + +/** + * Class AuthManager + * @package Swoft\Auth + */ +class AuthManager +{ + + const KEY = "authSession"; + + /** + * @Value("${config.auth.cache.prefix}") + * @var string + */ + private $prefix = "token_"; + + /** + * @var int + * @Value("${config.auth.token.lifetime}") + */ + protected $sessionDuration = 86400; + + /** + * @var bool + * @Value("${config.auth.cache.enable}") + */ + protected $cacheEnable = false; + + /** + * @Value("${config.auth.cache}") + * @var CacheInterface + */ + protected $cache; + + /** + * @Value("${config.auth.token.parser}") + * @var TokenParserInterface + */ + protected $tokenParser; + + + public function getSessionDuration() + { + return $this->sessionDuration; + } + + public function setSessionDuration($time) + { + $this->sessionDuration = $time; + } + + /** + * @return AuthSession; + */ + public function getSession() + { + return RequestContext::getContextDataByKey(self::KEY); + } + + public function setSession(AuthSession $session) + { + RequestContext::setContextData([self::KEY => $session]); + } + + /** + * @return bool + * + * Check if a user is currently logged in + */ + public function loggedIn() + { + return $this->getSession() instanceof AuthSession; + } + + /** + * @param $accountTypeName + * @param array $data + * @return AuthSession + */ + public function login(string $accountTypeName, array $data) + { + if (!$account = $this->getAccountType($accountTypeName)) { + throw new AuthException(ErrorCode::AUTH_INVALID_ACCOUNT_TYPE); + } + /** @var AuthResult $result */ + $result = $account->login($data); + if (!$result) { + throw new AuthException(ErrorCode::AUTH_LOGIN_FAILED); + } + $identity = $result->getIdentity(); + $session = $this->generateSession($accountTypeName, $identity, $data); + $this->setSession($session); + if ($this->cacheEnable === true) { + try { + $this->cache->set($this->getCacheKey($identity), $session->getToken(), $session->getExpirationTime()); + } catch (InvalidArgumentException $e) { + $err = sprintf("%s 参数无效",$session->getIdentity()); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,$err); + } + } + return $session; + } + + + protected function getCacheKey($identity) + { + return $this->prefix . $identity; + } + + /** + * @param string $accountTypeName + * @param string $identity + * @param array $data + * @return AuthSession + */ + public function generateSession(string $accountTypeName, string $identity, array $data = []) + { + $startTime = time(); + $exp = $startTime + (int)$this->sessionDuration; + $session = new AuthSession(); + $session + ->setExtendedData($data) + ->setExpirationTime($exp) + ->setCreateTime($startTime) + ->setIdentity($identity) + ->setAccountTypeName($accountTypeName); + $session->setExtendedData($data); + $token = $this->tokenParser->getToken($session); + $session->setToken($token); + return $session; + } + + /** + * @param $name + * @return AccountTypeInterface|null + */ + public function getAccountType($name) + { + if (!App::hasBean($name)) { + return null; + } + $account = App::getBean($name); + if (!$account instanceof AccountTypeInterface) { + return null; + } + return $account; + } + + /** + * @param $token + * @return bool + * @throws AuthException + */ + public function authenticateToken($token) + { + try { + /** @var AuthSession $session */ + $session = $this->tokenParser->getSession($token); + } catch (\Exception $e) { + throw new AuthException(ErrorCode::AUTH_TOKEN_INVALID); + } + + if (!$session) { + return false; + } + + if ($session->getExpirationTime() < time()) { + throw new AuthException(ErrorCode::AUTH_SESSION_EXPIRED); + } + + if (!$account = $this->getAccountType($session->getAccountTypeName())) { + throw new AuthException(ErrorCode::AUTH_SESSION_INVALID); + } + + if (!$account->authenticate($session->getIdentity())) { + throw new AuthException(ErrorCode::AUTH_TOKEN_INVALID); + } + + if ($this->cacheEnable === true) { + try { + $cache = $this->cache->get($this->getCacheKey($session->getIdentity())); + if (!$cache || $cache !== $token) { + throw new AuthException(ErrorCode::AUTH_TOKEN_INVALID); + } + } catch (InvalidArgumentException $e) { + $err = sprintf("%s 参数无效",$session->getIdentity()); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,$err); + } + } + $this->setSession($session); + return true; + } + + +} \ No newline at end of file diff --git a/src/Bean/AuthResult.php b/src/Bean/AuthResult.php new file mode 100644 index 0000000..949cbc4 --- /dev/null +++ b/src/Bean/AuthResult.php @@ -0,0 +1,63 @@ +identity; + } + + /** + * @param string $identity + */ + public function setIdentity(string $identity) + { + $this->identity = $identity; + } + + /** + * @return array + */ + public function getExtendedData(): array + { + return $this->extendedData; + } + + /** + * @param array $extendedData + */ + public function setExtendedData(array $extendedData): void + { + $this->extendedData = $extendedData; + } + + +} \ No newline at end of file diff --git a/src/Bean/AuthSession.php b/src/Bean/AuthSession.php new file mode 100644 index 0000000..7e79815 --- /dev/null +++ b/src/Bean/AuthSession.php @@ -0,0 +1,161 @@ + + */ + +namespace Swoft\Auth\Bean; + +use Swoft\Bean\Annotation\Bean; +use Swoft\Bean\Annotation\Scope; + +/** + * Class AuthSession + * @package Swoft\Auth\Bean + * @Bean(scope=Scope::PROTOTYPE) + */ +class AuthSession +{ + /** + * @var string User personal information credentials + */ + protected $identity=''; + + /** + * @var string Login method name + */ + protected $accountTypeName=''; + + /** + * @var string Authentication credentials + */ + protected $token=''; + + /** + * @var int Creation time + */ + protected $createTime=0; + + /** + * @var int + */ + protected $expirationTime=0; + + /** + * @var array Expand data, define it yourself + */ + protected $extendedData=[]; + + /** + * @return string + */ + public function getIdentity(): string + { + return $this->identity; + } + + /** + * @param string $identity + * @return AuthSession + */ + public function setIdentity(string $identity): AuthSession + { + $this->identity = $identity; + return $this; + } + + /** + * @return string + */ + public function getAccountTypeName(): string + { + return $this->accountTypeName; + } + + /** + * @param string $accountTypeName + * @return AuthSession + */ + public function setAccountTypeName(string $accountTypeName): AuthSession + { + $this->accountTypeName = $accountTypeName; + return $this; + } + + /** + * @return string + */ + public function getToken(): string + { + return $this->token; + } + + /** + * @param string $token + * @return AuthSession + */ + public function setToken(string $token): AuthSession + { + $this->token = $token; + return $this; + } + + /** + * @return int + */ + public function getCreateTime(): int + { + return $this->createTime; + } + + /** + * @param int $createTime + * @return AuthSession + */ + public function setCreateTime(int $createTime): AuthSession + { + $this->createTime = $createTime; + return $this; + } + + /** + * @return int + */ + public function getExpirationTime(): int + { + return $this->expirationTime; + } + + /** + * @param int $expirationTime + * @return AuthSession + */ + public function setExpirationTime(int $expirationTime): AuthSession + { + $this->expirationTime = $expirationTime; + return $this; + } + + /** + * @return array + */ + public function getExtendedData(): array + { + return $this->extendedData; + } + + /** + * @param array $extendedData + * @return AuthSession + */ + public function setExtendedData(array $extendedData): AuthSession + { + $this->extendedData = $extendedData; + return $this; + } + + +} \ No newline at end of file diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php new file mode 100644 index 0000000..444e4fc --- /dev/null +++ b/src/Bootstrap/CoreBean.php @@ -0,0 +1,38 @@ + + */ + +namespace Swoft\Auth\Bootstrap; + +use Swoft\Auth\AuthManager; +use Swoft\Auth\Helper\ErrorCodeHelper; +use Swoft\Auth\Parser\AuthorizationHeaderParser; +use Swoft\Auth\Parser\RequestHeaderParser; +use Swoft\Bean\Annotation\BootBean; +use Swoft\Core\BootBeanInterface; + +/** + * Class CoreBean + * @package Swoft\Auth\Bootstrap + * @BootBean() + */ +class CoreBean implements BootBeanInterface +{ + + /** + * @return array + */ + public function beans() + { + return [ + 'AuthRequestHeaderParser'=>AuthorizationHeaderParser::class, + 'AuthManager'=>AuthManager::class, + 'ErrorCodeHelper'=>ErrorCodeHelper::class + ]; + } +} \ No newline at end of file diff --git a/src/Constants/AuthConstants.php b/src/Constants/AuthConstants.php new file mode 100644 index 0000000..55350bb --- /dev/null +++ b/src/Constants/AuthConstants.php @@ -0,0 +1,28 @@ + + */ +namespace Swoft\Auth\Constants; + +class AuthConstants +{ + + const HEADER_KEY = 'Authorization'; + + const BASIC_USER_NAME = 'basicUsername'; + + const BASIC_PASSWORD = 'basicPassword'; + + const IS_LOGIN = 'isLogin'; + + const AUTH_SESSION = 'authSession'; + + const IDENTITY = 'identity'; + + const EXTEND_DATA = 'extendedData'; + +} \ No newline at end of file diff --git a/src/Exception/AuthException.php b/src/Exception/AuthException.php new file mode 100644 index 0000000..848d109 --- /dev/null +++ b/src/Exception/AuthException.php @@ -0,0 +1,23 @@ + + */ + +namespace Swoft\Auth\Exception; + +use Swoft\Exception\RuntimeException; +use Throwable; + +class AuthException extends RuntimeException +{ + + public function __construct(int $code = 0, string $message = "", Throwable $previous = null) + { + parent::__construct($message, $code, $previous); + } + +} \ No newline at end of file diff --git a/src/Helper/ErrorCode.php b/src/Helper/ErrorCode.php new file mode 100644 index 0000000..dcf3cbe --- /dev/null +++ b/src/Helper/ErrorCode.php @@ -0,0 +1,55 @@ + + */ + +namespace Swoft\Auth\Helper; + +/** + * User: sl + * Date: 2018/5/20 + * Time: 下午5:41 + * Interface ErrorCodeInterface + * @package Swoft\Auth\Helper + * @author April2 + */ +class ErrorCode +{ + /** + * 通用 + */ + const GENERAL_SYSTEM = 1010; + const GENERAL_NOT_IMPLEMENTED = 1020; + const GENERAL_NOT_FOUND = 1030; + + /** + * 用户认证 + */ + const AUTH_INVALID_ACCOUNT_TYPE = 2010; + const AUTH_LOGIN_FAILED = 2020; + const AUTH_TOKEN_INVALID = 2030; + const AUTH_SESSION_EXPIRED = 2040; + const AUTH_SESSION_INVALID = 2050; + + /** + * 访问控制 + */ + const ACCESS_DENIED = 3010; + + /** + * 客户端错误 + */ + const DATA_FAILED = 4010; + const DATA_NOT_FOUND = 4020; + + /** + * 服务器错误 + */ + const POST_DATA_NOT_PROVIDED = 5010; + const POST_DATA_INVALID = 5020; + +} \ No newline at end of file diff --git a/src/Helper/ErrorCodeHelper.php b/src/Helper/ErrorCodeHelper.php new file mode 100644 index 0000000..97e6abc --- /dev/null +++ b/src/Helper/ErrorCodeHelper.php @@ -0,0 +1,135 @@ + + */ + +namespace Swoft\Auth\Helper; + +use Swoft\Bean\Annotation\Value; +use Swoft\Helper\ArrayHelper; + +class ErrorCodeHelper +{ + + /** + * @var array + */ + protected $errors = [ + ErrorCode::GENERAL_SYSTEM => [ + 'statusCode' => 500, + 'message' => 'General: System Error' + ], + + ErrorCode::GENERAL_NOT_IMPLEMENTED => [ + 'statusCode' => 500, + 'message' => 'General: Not Implemented' + ], + + ErrorCode::GENERAL_NOT_FOUND => [ + 'statusCode' => 404, + 'message' => 'General: Not Found' + ], + + // Authentication + ErrorCode::AUTH_INVALID_ACCOUNT_TYPE => [ + 'statusCode' => 400, + 'message' => 'Authentication: Invalid Account Type' + ], + + ErrorCode::AUTH_LOGIN_FAILED => [ + 'statusCode' => 401, + 'message' => 'Authentication: Login Failed' + ], + + ErrorCode::AUTH_TOKEN_INVALID => [ + 'statusCode' => 401, + 'message' => 'Authentication: Login Failed' + ], + + ErrorCode::AUTH_SESSION_EXPIRED => [ + 'statusCode' => 401, + 'message' => 'Authentication: Session Expired' + ], + + ErrorCode::AUTH_SESSION_INVALID => [ + 'statusCode' => 401, + 'message' => 'Authentication: Session Invalid' + ], + + ErrorCode::ACCESS_DENIED => [ + 'statusCode' => 403, + 'message' => 'Access: Denied' + ], + + ErrorCode::DATA_FAILED => [ + 'statusCode' => 500, + 'message' => 'Data: Failed' + ], + + ErrorCode::DATA_NOT_FOUND => [ + 'statusCode' => 404, + 'message' => 'Data: Not Found' + ], + + ErrorCode::POST_DATA_NOT_PROVIDED => [ + 'statusCode' => 400, + 'message' => 'Postdata: Not provided' + ], + + ErrorCode::POST_DATA_INVALID => [ + 'statusCode' => 400, + 'message' => 'Postdata: Invalid' + ] + ]; + + /** + * @param $code + * + * @return array|null + */ + public function get($code) + { + return $this->has($code) ? $this->getErrors()[$code] : null; + } + + /** + * @param $code + * + * @return bool + */ + public function has($code) + { + return array_key_exists($code, $this->getErrors()); + } + + /** + * @param $code + * @param $message + * @param $statusCode + * + * @return static + */ + public function error($code, $message, $statusCode) + { + $this->errors[$code] = [ + 'statusCode' => $statusCode, + 'message' => $message + ]; + + return $this; + } + + /** + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + +} \ No newline at end of file diff --git a/src/Mapping/AccountTypeInterface.php b/src/Mapping/AccountTypeInterface.php new file mode 100644 index 0000000..f9a5b3a --- /dev/null +++ b/src/Mapping/AccountTypeInterface.php @@ -0,0 +1,37 @@ + + */ + +namespace Swoft\Auth\Mapping; + +use Psr\Http\Message\ServerRequestInterface; + +interface AuthHandleInterface +{ + /** + * @param \Psr\Http\Message\ServerRequestInterface $request + * @return \Psr\Http\Message\ServerRequestInterface + */ + public function parse(ServerRequestInterface $request): ServerRequestInterface; + +} \ No newline at end of file diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php new file mode 100644 index 0000000..9bad8c0 --- /dev/null +++ b/src/Middleware/AuthMiddleware.php @@ -0,0 +1,39 @@ + + */ + +namespace Swoft\Auth\Middleware; + + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Swoft\App; +use Swoft\Auth\Parser\AuthorizationHeaderParser; +use Swoft\Http\Message\Middleware\MiddlewareInterface; + +class AuthMiddleware implements MiddlewareInterface +{ + + /** + * Process an incoming server request and return a response, optionally delegating + * response creation to a handler. + * + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Server\RequestHandlerInterface $handler + * @return \Psr\Http\Message\ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + /** @var AuthorizationHeaderParser $parser */ + $parser = App::getBean("AuthRequestHeaderParser"); + $request = $parser->parse($request); + $response = $handler->handle($request); + return $response; + } +} \ No newline at end of file diff --git a/src/Parser/AuthorizationHeaderParser.php b/src/Parser/AuthorizationHeaderParser.php new file mode 100644 index 0000000..0e19690 --- /dev/null +++ b/src/Parser/AuthorizationHeaderParser.php @@ -0,0 +1,76 @@ + + */ + +namespace Swoft\Auth\Parser; + +use Psr\Http\Message\ServerRequestInterface; +use Swoft\App; +use Swoft\Auth\Constants\AuthConstants; +use Swoft\Auth\Mapping\AuthHandleInterface; +use Swoft\Bean\Annotation\Value; +use Swoft\Helper\ArrayHelper; +use Swoft\Http\Server\Parser\RequestParserInterface; + +class AuthorizationHeaderParser implements RequestParserInterface +{ + /** + * The parsers + * + * @var array + */ + private $authTypes = []; + + /** + * @Value("${config.auth.types}") + * @var array + */ + private $types = []; + + private $headerKey = AuthConstants::HEADER_KEY; + + /** + * @param \Psr\Http\Message\ServerRequestInterface $request + * @return \Psr\Http\Message\ServerRequestInterface + */ + public function parse(ServerRequestInterface $request): ServerRequestInterface + { + $authValue = $request->getHeaderLine($this->headerKey); + $type = $this->getHeadString($authValue); + if (isset($this->mergeTypes()[$type])) { + /** @var AuthHandleInterface $handler */ + $handler = App::getBean($type); + $request = $handler->parse($request); + } + return $request; + } + + + private function getHeadString(string $val):string + { + return explode(' ',$val)[0] ?? ''; + } + + + private function mergeTypes(): array + { + if (empty($this->authTypes)) { + $this->authTypes = ArrayHelper::merge($this->types, $this->defaultTypes()); + } + return $this->authTypes; + } + + + public function defaultTypes(): array + { + return [ + BearerTokenParser::NAME => BearerTokenParser::class, + BasicAuthParser::NAME => BasicAuthParser::class + ]; + } +} \ No newline at end of file diff --git a/src/Parser/AuthorizationParserInterface.php b/src/Parser/AuthorizationParserInterface.php new file mode 100644 index 0000000..9c9ef9e --- /dev/null +++ b/src/Parser/AuthorizationParserInterface.php @@ -0,0 +1,20 @@ + + */ + +namespace Swoft\Auth\Parser; + + +use Psr\Http\Message\ServerRequestInterface; + +interface AuthorizationParserInterface +{ + + public function parse(ServerRequestInterface $request); + +} \ No newline at end of file diff --git a/src/Parser/BasicAuthParser.php b/src/Parser/BasicAuthParser.php new file mode 100644 index 0000000..f827710 --- /dev/null +++ b/src/Parser/BasicAuthParser.php @@ -0,0 +1,58 @@ + + */ + +namespace Swoft\Auth\Parser; + + +use Psr\Http\Message\ServerRequestInterface; +use Swoft\Auth\Constants\AuthConstants; +use Swoft\Auth\Mapping\AuthHandleInterface; + +class BasicAuthParser implements AuthHandleInterface +{ + + const NAME = 'Basic'; + + /** + * @param \Psr\Http\Message\ServerRequestInterface $request + * @return \Psr\Http\Message\ServerRequestInterface + */ + public function parse(ServerRequestInterface $request): ServerRequestInterface + { + $authHeader = $request->getHeaderLine(AuthConstants::HEADER_KEY) ?? ''; + $basic = $this->parseValue($authHeader); + if($basic){ + $request = $request + ->withAttribute(AuthConstants::BASIC_USER_NAME,$this->getUsername($basic)) + ->withAttribute(AuthConstants::BASIC_PASSWORD,$this->getPassword($basic)); + } + return $request; + } + + protected function getUsername(array $basic) + { + return $basic[0]??''; + } + + protected function getPassword(array $basic){ + return $basic[1]??''; + } + + protected function parseValue($string):array + { + if (strpos(trim($string), self::NAME) !== 0) { + return null; + } + $val = preg_replace('/.*\s/', '', $string); + if(!$val){ + return null; + } + return explode(':',base64_decode($val)); + } +} \ No newline at end of file diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php new file mode 100644 index 0000000..35f205f --- /dev/null +++ b/src/Parser/BearerTokenParser.php @@ -0,0 +1,54 @@ + + */ + +namespace Swoft\Auth\Parser; + + +use Psr\Http\Message\ServerRequestInterface; +use Swoft\App; +use Swoft\Auth\AuthManager; +use Swoft\Auth\Constants\AuthConstants; +use Swoft\Auth\Mapping\AuthHandleInterface; + +class BearerTokenParser implements AuthHandleInterface +{ + + const NAME = 'Bearer'; + + /** + * @param \Psr\Http\Message\ServerRequestInterface $request + * @return \Psr\Http\Message\ServerRequestInterface + */ + public function parse(ServerRequestInterface $request): ServerRequestInterface + { + $token = $this->getToken($request); + /** @var AuthManager $manager */ + $manager = App::getBean("AuthManager"); + if($token){ + $res = $manager->authenticateToken($token); + $request = $request->withAttribute(AuthConstants::IS_LOGIN,$res); + } + return $request; + } + + protected function getToken(ServerRequestInterface $request) + { + $authHeader = $request->getHeaderLine(AuthConstants::HEADER_KEY) ?? ''; + $authQuery = $request->getQueryParams()['token'] ?? ''; + return $authQuery ? $authQuery : $this->parseValue($authHeader); + } + + protected function parseValue($string){ + if (strpos(trim($string), self::NAME) !== 0) { + return null; + } + return preg_replace('/.*\s/', '', $string); + } + +} \ No newline at end of file diff --git a/src/Parser/JWTTokenParser.php b/src/Parser/JWTTokenParser.php new file mode 100644 index 0000000..1af61df --- /dev/null +++ b/src/Parser/JWTTokenParser.php @@ -0,0 +1,141 @@ +create( + $session->getAccountTypeName(), + $session->getIdentity(), + $session->getCreateTime(), + $session->getExpirationTime(), + $session->getExtendedData() + ); + return $this->encode($tokenData); + } + + /** + * @param string $token + * @return AuthSession + */ + public function getSession(string $token):AuthSession + { + $tokenData = $this->decode($token); + return (new AuthSession()) + ->setAccountTypeName($tokenData->iss) + ->setIdentity($tokenData->sub) + ->setCreateTime($tokenData->iat) + ->setExpirationTime($tokenData->exp) + ->setToken($token) + ->setExtendedData($tokenData->data); + } + + protected function create(string $issuer, string $user, int $iat,int $exp,array $data):array + { + + return [ + /* + The iss (issuer) claim identifies the principal + that issued the JWT. The processing of this claim + is generally application specific. + The iss value is a case-sensitive string containing + a StringOrURI value. Use of this claim is OPTIONAL. + ------------------------------------------------*/ + "iss" => $issuer, + + /* + The sub (subject) claim identifies the principal + that is the subject of the JWT. The Claims in a + JWT are normally statements about the subject. + The subject value MUST either be scoped to be + locally unique in the context of the issuer or + be globally unique. The processing of this claim + is generally application specific. The sub value + is a case-sensitive string containing a + StringOrURI value. Use of this claim is OPTIONAL. + ------------------------------------------------*/ + "sub" => $user, + + /* + The iat (issued at) claim identifies the time at + which the JWT was issued. This claim can be used + to determine the age of the JWT. Its value MUST + be a number containing a NumericDate value. + Use of this claim is OPTIONAL. + ------------------------------------------------*/ + "iat" => $iat, + + /* + The exp (expiration time) claim identifies the + expiration time on or after which the JWT MUST NOT + be accepted for processing. The processing of the + exp claim requires that the current date/time MUST + be before the expiration date/time listed in the + exp claim. Implementers MAY provide for some small + leeway, usually no more than a few minutes, + to account for clock skew. Its value MUST be a + number containing a NumericDate value. + Use of this claim is OPTIONAL. + ------------------------------------------------*/ + "exp" => $exp, + + /* + Expand data + ------------------------------------------------*/ + "data" => $data, + ]; + } + + + public function encode($token): string + { + return (string)JWT::encode($token, $this->secret, $this->algorithm); + } + + + public function decode($token) + { + return JWT::decode($token, $this->secret, [$this->algorithm]); + } + + +} \ No newline at end of file diff --git a/src/Parser/TokenParserInterface.php b/src/Parser/TokenParserInterface.php new file mode 100644 index 0000000..bf1e4bf --- /dev/null +++ b/src/Parser/TokenParserInterface.php @@ -0,0 +1,30 @@ + + */ + +namespace Swoft\Auth\Parser; + + +use Swoft\Auth\Bean\AuthSession; + +interface TokenParserInterface +{ + /** + * @param AuthSession $session + * @return string + */ + public function getToken(AuthSession $session):string ; + + /** + * @param string $token + * @return AuthSession + */ + public function getSession(string $token):AuthSession ; + + +} \ No newline at end of file diff --git a/test/.env b/test/.env new file mode 100644 index 0000000..c0280f4 --- /dev/null +++ b/test/.env @@ -0,0 +1,50 @@ +# test config +TEST_NAME=test +TEST_URI=127.0.0.1:6378 +TEST_MAX_IDEL=2 +TEST_MAX_ACTIVE=2 +TEST_MAX_WAIT=2 +TEST_TIMEOUT=2 +TEST_BALANCER=r1 +TEST_USE_PROVIDER=true +TEST_PROVIDER=c1 + +# the pool of master nodes pool +DB_NAME=master2 +DB_URI=127.0.0.1:3302,127.0.0.1:3302 +DB_MAX_IDEL=2 +DB_MAX_ACTIVE=2 +DB_MAX_WAIT=2 +DB_TIMEOUT=2 +DB_USE_PROVIDER=true +DB_BALANCER=random2 +DB_PROVIDER=consul2 + +# the pool of slave nodes pool +DB_SLAVE_NAME=slave2 +DB_SLAVE_URI=127.0.0.1:3306/test?user=root&password=&charset=utf8,127.0.0.1:3306/test?user=root&password=&charset=utf8 +DB_SLAVE_MAX_IDEL=2 +DB_SLAVE_MAX_ACTIVE=2 +DB_SLAVE_MAX_WAIT=2 +DB_SLAVE_TIMEOUT=2 +DB_SLAVE_USE_PROVIDER=false +DB_SLAVE_BALANCER=random +DB_SLAVE_PROVIDER=consul2 + +# the pool of redis +REDIS_NAME=redis2 +REDIS_URI=127.0.0.1:2222,127.0.0.1:2222 +REDIS_MAX_IDEL=2 +REDIS_MAX_ACTIVE=2 +REDIS_MAX_WAIT=2 +REDIS_TIMEOUT=2 +REDIS_USE_PROVIDER=true +REDIS_BALANCER=random2 +REDIS_PROVIDER=consul2 + + +# consul provider +PROVIDER_CONSUL_ADDRESS=http://127.0.0.1:82 +PROVIDER_CONSUL_TAGS=1,2 +PROVIDER_CONSUL_TIMEOUT=2 +PROVIDER_CONSUL_INTERVAL=2 diff --git a/test/bootstrap.php b/test/bootstrap.php new file mode 100644 index 0000000..83e1718 --- /dev/null +++ b/test/bootstrap.php @@ -0,0 +1,30 @@ +bootstrap(); + +\Swoft\Bean\BeanFactory::reload([ + 'application' => [ + 'class' => \Swoft\Testing\Application::class, + 'inTest' => true + ], +]); +$initApplicationContext = new \Swoft\Core\InitApplicationContext(); +$initApplicationContext->init(); + + diff --git a/test/config/beans/base.php b/test/config/beans/base.php new file mode 100644 index 0000000..b993871 --- /dev/null +++ b/test/config/beans/base.php @@ -0,0 +1,3 @@ + [ + "class" => \Swoft\Log\FileHandler::class, + "logFile" => "@runtime/logs/notice.log", + 'formatter' => '${lineFormatter}', + "levels" => [ + \Swoft\Log\Logger::NOTICE, + \Swoft\Log\Logger::INFO, + \Swoft\Log\Logger::DEBUG, + \Swoft\Log\Logger::TRACE, + ] + ], + "applicationHandler" => [ + "class" => \Swoft\Log\FileHandler::class, + "logFile" => "@runtime/logs/error.log", + 'formatter' => '${lineFormatter}', + "levels" => [ + \Swoft\Log\Logger::ERROR, + \Swoft\Log\Logger::WARNING + ] + ], + "logger" => [ + "class" => \Swoft\Log\Logger::class, + "name" => APP_NAME, + "flushInterval" => 100, + "flushRequest" => true, + "handlers" => [ + '${noticeHandler}', + '${applicationHandler}' + ] + ], +]; diff --git a/test/config/define.php b/test/config/define.php new file mode 100644 index 0000000..e18d417 --- /dev/null +++ b/test/config/define.php @@ -0,0 +1,26 @@ + BASE_PATH, + '@app' => '@root/app', + '@res' => '@root/resources', + '@runtime' => '@root/runtime', + '@configs' => '@root/config', + '@resources' => '@root/resources', + '@beans' => '@configs/beans', + '@properties' => '@configs/properties', + '@console' => '@beans/console.php', +]; +App::setAliases($aliases); diff --git a/test/config/properties/app.php b/test/config/properties/app.php new file mode 100644 index 0000000..42095f5 --- /dev/null +++ b/test/config/properties/app.php @@ -0,0 +1,21 @@ + '1.0', + 'autoInitBean' => true, + 'beanScan' => [ + 'Swoft\\Http\\Server\\Test\\Testing' => BASE_PATH."/Testing" + ], + 'I18n' => [ + 'sourceLanguage' => '@root/resources/messages/', + ], + 'env' => 'Base', + 'auth' =>[ + 'cache'=>'' + ], + 'Service' => [ + 'user' => [ + 'timeout' => 3000 + ] + ], + 'cache' => require dirname(__FILE__) . DS . "cache.php", +]; diff --git a/test/config/properties/cache.php b/test/config/properties/cache.php new file mode 100644 index 0000000..30c0bce --- /dev/null +++ b/test/config/properties/cache.php @@ -0,0 +1,17 @@ + [ + 'name' => 'redis1', + "uri" => [ + '127.0.0.1:1111', + '127.0.0.1:1111', + ], + "maxIdel" => 1, + "maxActive" => 1, + "maxWait" => 1, + "timeout" => 1, + "balancer" => 'random1', + "useProvider" => true, + 'provider' => 'consul1', + ], +]; diff --git a/test/config/server.php b/test/config/server.php new file mode 100644 index 0000000..b83d552 --- /dev/null +++ b/test/config/server.php @@ -0,0 +1,37 @@ + [ + 'pfile' => env('PFILE', '/tmp/swoft.pid'), + 'pname' => env('PNAME', 'php-swoft'), + 'tcpable' => env('TCPABLE', true), + 'cronable' => env('CRONABLE', false), + 'autoReload' => env('AUTO_RELOAD', true), + ], + 'tcp' => [ + 'host' => env('TCP_HOST', '0.0.0.0'), + 'port' => env('TCP_PORT', 8099), + 'mode' => env('TCP_MODE', SWOOLE_PROCESS), + 'type' => env('TCP_TYPE', SWOOLE_SOCK_TCP), + 'package_max_length' => env('TCP_PACKAGE_MAX_LENGTH', 2048), + 'open_eof_check' => env('TCP_OPEN_EOF_CHECK', false), + ], + 'http' => [ + 'host' => env('HTTP_HOST', '0.0.0.0'), + 'port' => env('HTTP_PORT', 80), + 'mode' => env('HTTP_MODE', SWOOLE_PROCESS), + 'type' => env('HTTP_TYPE', SWOOLE_SOCK_TCP), + ], + 'crontab' => [ + 'task_count' => env('CRONTAB_TASK_COUNT', 1024), + 'task_queue' => env('CRONTAB_TASK_QUEUE', 2048), + ], + 'setting' => [ + 'worker_num' => env('WORKER_NUM', 1), + 'max_request' => env('MAX_REQUEST', 10000), + 'daemonize' => env('DAEMONIZE', 0), + 'dispatch_mode' => env('DISPATCH_MODE', 2), + 'log_file' => env('LOG_FILE', '@runtime/logs/swoole.log'), + 'task_worker_num' => env('TASK_WORKER_NUM', 1), + 'upload_tmp_dir' => env('UPLOAD_TMP_DIR', '@runtime/uploadfiles'), + ], +]; From 7cb5c42a1fd1bd5dc6039cb12fc6e489e74521ee Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 21 May 2018 10:32:26 +0800 Subject: [PATCH 02/24] add acl --- src/AuthManager.php | 7 ++- src/AuthUserService.php | 52 +++++++++++++++++++++++ src/Bootstrap/CoreBean.php | 9 ++-- src/Constants/ServiceConstants.php | 24 +++++++++++ src/Middleware/AclMiddleware.php | 68 ++++++++++++++++++++++++++++++ src/Parser/BearerTokenParser.php | 5 ++- 6 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 src/AuthUserService.php create mode 100644 src/Constants/ServiceConstants.php create mode 100644 src/Middleware/AclMiddleware.php diff --git a/src/AuthManager.php b/src/AuthManager.php index d118587..0644c22 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -15,6 +15,7 @@ use Swoft\App; use Swoft\Auth\Bean\AuthResult; use Swoft\Auth\Bean\AuthSession; +use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Parser\TokenParserInterface; @@ -28,8 +29,6 @@ class AuthManager { - const KEY = "authSession"; - /** * @Value("${config.auth.cache.prefix}") * @var string @@ -76,12 +75,12 @@ public function setSessionDuration($time) */ public function getSession() { - return RequestContext::getContextDataByKey(self::KEY); + return RequestContext::getContextDataByKey(AuthConstants::AUTH_SESSION); } public function setSession(AuthSession $session) { - RequestContext::setContextData([self::KEY => $session]); + RequestContext::setContextData([AuthConstants::AUTH_SESSION => $session]); } /** diff --git a/src/AuthUserService.php b/src/AuthUserService.php new file mode 100644 index 0000000..c456345 --- /dev/null +++ b/src/AuthUserService.php @@ -0,0 +1,52 @@ + + */ + +namespace Swoft\Auth; + + +use Swoft\Auth\Bean\AuthSession; +use Swoft\Auth\Constants\AuthConstants; +use Swoft\Core\RequestContext; + +class AuthUserService +{ + + + public function getUserIdentity(): string + { + return $this->getSession()->getIdentity(); + } + + + public function getUserExtendData(): array + { + return $this->getSession()->getExtendedData(); + } + + + public function getSession(): AuthSession + { + return RequestContext::getContextDataByKey(AuthConstants::AUTH_SESSION); + } + + /** + * @param string $controller 控制器名 + * @param string $action 方法名 + * @return bool + */ + public function auth(string $controller,string $action): bool + { + $id = $this->getUserIdentity(); + if ($id) { + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index 444e4fc..b3d728d 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -10,6 +10,8 @@ namespace Swoft\Auth\Bootstrap; use Swoft\Auth\AuthManager; +use Swoft\Auth\AuthUserService; +use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Helper\ErrorCodeHelper; use Swoft\Auth\Parser\AuthorizationHeaderParser; use Swoft\Auth\Parser\RequestHeaderParser; @@ -30,9 +32,10 @@ class CoreBean implements BootBeanInterface public function beans() { return [ - 'AuthRequestHeaderParser'=>AuthorizationHeaderParser::class, - 'AuthManager'=>AuthManager::class, - 'ErrorCodeHelper'=>ErrorCodeHelper::class + ServiceConstants::AUTH_REQUEST_HEADER_PARSER=>AuthorizationHeaderParser::class, + ServiceConstants::AUTH_MANAGER=>AuthManager::class, + ServiceConstants::AUTH_ERROR_CODE_HELPER=>ErrorCodeHelper::class, + ServiceConstants::AUTH_USERS_SERVICE=>AuthUserService::class ]; } } \ No newline at end of file diff --git a/src/Constants/ServiceConstants.php b/src/Constants/ServiceConstants.php new file mode 100644 index 0000000..d215c92 --- /dev/null +++ b/src/Constants/ServiceConstants.php @@ -0,0 +1,24 @@ + + */ + +namespace Swoft\Auth\Constants; + + +class ServiceConstants +{ + + const AUTH_REQUEST_HEADER_PARSER = "AuthRequestHeaderParser"; + + const AUTH_MANAGER = "AuthManager"; + + const AUTH_ERROR_CODE_HELPER = "AuthErrorCodeHelper"; + + const AUTH_USERS_SERVICE = "AuthUserService"; + +} \ No newline at end of file diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php new file mode 100644 index 0000000..18c756d --- /dev/null +++ b/src/Middleware/AclMiddleware.php @@ -0,0 +1,68 @@ + + */ + +namespace Swoft\Auth\Middleware; + + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Swoft\App; +use Swoft\Auth\AuthUserService; +use Swoft\Auth\Constants\ServiceConstants; +use Swoft\Auth\Exception\AuthException; +use Swoft\Auth\Helper\ErrorCode; +use Swoft\Http\Message\Middleware\MiddlewareInterface; + +/** + * Class AclMiddleware + * @package Swoft\Auth\Middleware + * + */ +class AclMiddleware implements MiddlewareInterface +{ + + /** + * Process an incoming server request and return a response, optionally delegating + * response creation to a handler. + * + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Server\RequestHandlerInterface $handler + * @return \Psr\Http\Message\ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; + $handlerArray = self::getHandlerArray($requestHandler); + if ($requestHandler && is_array($handlerArray)) { + /** @var AuthUserService $service */ + $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); + $flag = $service->auth($handlerArray[0], $handlerArray[1]); + if (!$flag) { + throw new AuthException(ErrorCode::ACCESS_DENIED); + } + } + $response = $handler->handle($request); + return $response; + } + + /** + * @param string $handler + * @return array|null + */ + public static function getHandlerArray(string $handler) + { + $segments = explode('@', trim($handler)); + if (!isset($segments[1])) { + return null; + } + return $segments; + } + +} \ No newline at end of file diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php index 35f205f..acd8cbb 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/BearerTokenParser.php @@ -13,8 +13,11 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\App; use Swoft\Auth\AuthManager; +use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Constants\AuthConstants; +use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Mapping\AuthHandleInterface; +use Swoft\Core\RequestContext; class BearerTokenParser implements AuthHandleInterface { @@ -29,7 +32,7 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface { $token = $this->getToken($request); /** @var AuthManager $manager */ - $manager = App::getBean("AuthManager"); + $manager = App::getBean(ServiceConstants::AUTH_MANAGER); if($token){ $res = $manager->authenticateToken($token); $request = $request->withAttribute(AuthConstants::IS_LOGIN,$res); From 33424362bb5633fa1446630c2f59c872431f593c Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 21 May 2018 18:41:18 +0800 Subject: [PATCH 03/24] fit bug --- README.md | 41 +++++++++++++++++++++++++++- src/AuthManager.php | 2 +- src/AuthUserService.php | 18 ++++++++---- src/Bean/AuthResult.php | 6 +++- src/Bean/AuthSession.php | 12 ++++---- src/Bootstrap/CoreBean.php | 10 ++++--- src/Helper/ErrorCodeHelper.php | 11 +++++--- src/Mapping/AccountTypeInterface.php | 4 +-- src/Middleware/AclMiddleware.php | 8 +++++- src/Middleware/AuthMiddleware.php | 6 ++++ 10 files changed, 92 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index a36abe5..25de694 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,48 @@ composer require swoft/auth ```php -稍后再补... +codeHelper: +/** + * @ExceptionHandler() + */ +class SwoftExceptionHandler +{ +/** + * @Inject() + * @var ErrorCodeHelper + */ + protected $authHelper; + + + /** + * @Handler(AuthException::class) + * @param Response $response + * @param \Throwable $t + * @return Response + */ + public function handleAuthException(Response $response, \Throwable $t){ + $errorCode = $t->getCode(); + $statusCode = 500; + $message = $t->getMessage(); + + if ($this->authHelper->has($errorCode)) { + $defaultMessage = $this->authHelper->get($errorCode); + $statusCode = $defaultMessage['statusCode']; + if (!$message) { + $message = $defaultMessage['message']; + } + } + $error = [ + 'code' => $errorCode, + 'message' => $message ?: 'Unspecified error', + ]; + $response = $response->withStatus($statusCode)->json($error); + return $response; + } + +} ``` ## Unit testing diff --git a/src/AuthManager.php b/src/AuthManager.php index 0644c22..ad92b48 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -9,7 +9,6 @@ namespace Swoft\Auth; -use App\Component\Auth\Account\AccountTypeInterface; use Psr\SimpleCache\CacheInterface; use Psr\SimpleCache\InvalidArgumentException; use Swoft\App; @@ -18,6 +17,7 @@ use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; +use Swoft\Auth\Mapping\AccountTypeInterface; use Swoft\Auth\Parser\TokenParserInterface; use Swoft\Bean\Annotation\Value; use Swoft\Core\RequestContext; diff --git a/src/AuthUserService.php b/src/AuthUserService.php index c456345..bb70049 100644 --- a/src/AuthUserService.php +++ b/src/AuthUserService.php @@ -20,19 +20,27 @@ class AuthUserService public function getUserIdentity(): string { - return $this->getSession()->getIdentity(); + if(!$this->getSession()){ + return ''; + } + return $this->getSession()->getIdentity() ?? ''; } public function getUserExtendData(): array { - return $this->getSession()->getExtendedData(); + if(!$this->getSession()){ + return []; + } + return $this->getSession()->getExtendedData() ?? []; } - - public function getSession(): AuthSession + /** + * @return AuthSession |null + */ + public function getSession() { - return RequestContext::getContextDataByKey(AuthConstants::AUTH_SESSION); + return RequestContext::getContextDataByKey(AuthConstants::AUTH_SESSION) ?? null; } /** diff --git a/src/Bean/AuthResult.php b/src/Bean/AuthResult.php index 949cbc4..11e9e1f 100644 --- a/src/Bean/AuthResult.php +++ b/src/Bean/AuthResult.php @@ -37,10 +37,12 @@ public function getIdentity(): string /** * @param string $identity + * @return AuthResult */ public function setIdentity(string $identity) { $this->identity = $identity; + return $this; } /** @@ -53,10 +55,12 @@ public function getExtendedData(): array /** * @param array $extendedData + * @return AuthResult */ - public function setExtendedData(array $extendedData): void + public function setExtendedData(array $extendedData) { $this->extendedData = $extendedData; + return $this; } diff --git a/src/Bean/AuthSession.php b/src/Bean/AuthSession.php index 7e79815..0557e63 100644 --- a/src/Bean/AuthSession.php +++ b/src/Bean/AuthSession.php @@ -61,7 +61,7 @@ public function getIdentity(): string * @param string $identity * @return AuthSession */ - public function setIdentity(string $identity): AuthSession + public function setIdentity(string $identity) { $this->identity = $identity; return $this; @@ -79,7 +79,7 @@ public function getAccountTypeName(): string * @param string $accountTypeName * @return AuthSession */ - public function setAccountTypeName(string $accountTypeName): AuthSession + public function setAccountTypeName(string $accountTypeName) { $this->accountTypeName = $accountTypeName; return $this; @@ -97,7 +97,7 @@ public function getToken(): string * @param string $token * @return AuthSession */ - public function setToken(string $token): AuthSession + public function setToken(string $token) { $this->token = $token; return $this; @@ -115,7 +115,7 @@ public function getCreateTime(): int * @param int $createTime * @return AuthSession */ - public function setCreateTime(int $createTime): AuthSession + public function setCreateTime(int $createTime) { $this->createTime = $createTime; return $this; @@ -133,7 +133,7 @@ public function getExpirationTime(): int * @param int $expirationTime * @return AuthSession */ - public function setExpirationTime(int $expirationTime): AuthSession + public function setExpirationTime(int $expirationTime) { $this->expirationTime = $expirationTime; return $this; @@ -151,7 +151,7 @@ public function getExtendedData(): array * @param array $extendedData * @return AuthSession */ - public function setExtendedData(array $extendedData): AuthSession + public function setExtendedData(array $extendedData) { $this->extendedData = $extendedData; return $this; diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index b3d728d..26e026c 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -32,10 +32,12 @@ class CoreBean implements BootBeanInterface public function beans() { return [ - ServiceConstants::AUTH_REQUEST_HEADER_PARSER=>AuthorizationHeaderParser::class, - ServiceConstants::AUTH_MANAGER=>AuthManager::class, - ServiceConstants::AUTH_ERROR_CODE_HELPER=>ErrorCodeHelper::class, - ServiceConstants::AUTH_USERS_SERVICE=>AuthUserService::class + ServiceConstants::AUTH_REQUEST_HEADER_PARSER => [ + 'class' => AuthorizationHeaderParser::class + ], + ServiceConstants::AUTH_MANAGER => [ + 'class' => AuthManager::class + ] ]; } } \ No newline at end of file diff --git a/src/Helper/ErrorCodeHelper.php b/src/Helper/ErrorCodeHelper.php index 97e6abc..b71aa1c 100644 --- a/src/Helper/ErrorCodeHelper.php +++ b/src/Helper/ErrorCodeHelper.php @@ -9,9 +9,13 @@ namespace Swoft\Auth\Helper; -use Swoft\Bean\Annotation\Value; -use Swoft\Helper\ArrayHelper; +use Swoft\Bean\Annotation\Bean; +/** + * Class ErrorCodeHelper + * @package Swoft\Auth\Helper + * @Bean() + */ class ErrorCodeHelper { @@ -110,8 +114,7 @@ public function has($code) * @param $code * @param $message * @param $statusCode - * - * @return static + * @return ErrorCodeHelper */ public function error($code, $message, $statusCode) { diff --git a/src/Mapping/AccountTypeInterface.php b/src/Mapping/AccountTypeInterface.php index f9a5b3a..e19c693 100644 --- a/src/Mapping/AccountTypeInterface.php +++ b/src/Mapping/AccountTypeInterface.php @@ -6,9 +6,7 @@ * Time: 下午3:15 */ -namespace App\Component\Auth\Account; - - +namespace Swoft\Auth\Mapping; use Swoft\Auth\Bean\AuthResult; diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 18c756d..1403514 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -18,12 +18,13 @@ use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; +use Swoft\Bean\Annotation\Bean; use Swoft\Http\Message\Middleware\MiddlewareInterface; /** * Class AclMiddleware * @package Swoft\Auth\Middleware - * + * @Bean() */ class AclMiddleware implements MiddlewareInterface { @@ -41,6 +42,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; $handlerArray = self::getHandlerArray($requestHandler); if ($requestHandler && is_array($handlerArray)) { + + if(!App::hasBean(ServiceConstants::AUTH_USERS_SERVICE)){ + $error = sprintf("need AuthUserService %s",$requestHandler); + throw new AuthException(ErrorCode::POST_DATA_INVALID,$error); + } /** @var AuthUserService $service */ $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); $flag = $service->auth($handlerArray[0], $handlerArray[1]); diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index 9bad8c0..ae9ca26 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -15,8 +15,14 @@ use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; use Swoft\Auth\Parser\AuthorizationHeaderParser; +use Swoft\Bean\Annotation\Bean; use Swoft\Http\Message\Middleware\MiddlewareInterface; +/** + * Class AuthMiddleware + * @package Swoft\Auth\Middleware + * @Bean() + */ class AuthMiddleware implements MiddlewareInterface { From bf6d905903dc8745ac46ef4d959bff5a7b26f70e Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 21 May 2018 19:05:51 +0800 Subject: [PATCH 04/24] change readme --- README.md | 46 +++++----------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 25de694..761001a 100644 --- a/README.md +++ b/README.md @@ -12,50 +12,14 @@ composer require swoft/auth ## Document -```php - -codeHelper: - -/** - * @ExceptionHandler() - */ -class SwoftExceptionHandler -{ +- BasicAuth +- BearerToken +- Acl +- CodeHelper -/** - * @Inject() - * @var ErrorCodeHelper - */ - protected $authHelper; - - - /** - * @Handler(AuthException::class) - * @param Response $response - * @param \Throwable $t - * @return Response - */ - public function handleAuthException(Response $response, \Throwable $t){ - $errorCode = $t->getCode(); - $statusCode = 500; - $message = $t->getMessage(); +```php - if ($this->authHelper->has($errorCode)) { - $defaultMessage = $this->authHelper->get($errorCode); - $statusCode = $defaultMessage['statusCode']; - if (!$message) { - $message = $defaultMessage['message']; - } - } - $error = [ - 'code' => $errorCode, - 'message' => $message ?: 'Unspecified error', - ]; - $response = $response->withStatus($statusCode)->json($error); - return $response; - } -} ``` ## Unit testing From 2035968efed1029a1e3ccd0682b5cd5858bd8d73 Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 21 May 2018 19:21:59 +0800 Subject: [PATCH 05/24] fix jwt bug --- README.md | 1 + src/AuthManager.php | 15 +++++++++++++-- src/Constants/ServiceConstants.php | 2 -- src/Middleware/AuthMiddleware.php | 3 ++- src/Parser/AuthorizationHeaderParser.php | 2 +- src/Parser/BasicAuthParser.php | 6 ++++++ src/Parser/BearerTokenParser.php | 8 ++++++-- src/Parser/JWTTokenParser.php | 2 ++ 8 files changed, 31 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 761001a..6ff994f 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ composer require swoft/auth - BasicAuth - BearerToken +- JWT - Acl - CodeHelper diff --git a/src/AuthManager.php b/src/AuthManager.php index ad92b48..69ed973 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -18,6 +18,7 @@ use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AccountTypeInterface; +use Swoft\Auth\Parser\JWTTokenParser; use Swoft\Auth\Parser\TokenParserInterface; use Swoft\Bean\Annotation\Value; use Swoft\Core\RequestContext; @@ -146,7 +147,7 @@ public function generateSession(string $accountTypeName, string $identity, array ->setIdentity($identity) ->setAccountTypeName($accountTypeName); $session->setExtendedData($data); - $token = $this->tokenParser->getToken($session); + $token = $this->getTokenParser()->getToken($session); $session->setToken($token); return $session; } @@ -167,6 +168,15 @@ public function getAccountType($name) return $account; } + + public function getTokenParser():TokenParserInterface + { + if(empty($this->tokenParser)){ + $this->tokenParser = App::getBean(JWTTokenParser::class); + } + return $this->tokenParser; + } + /** * @param $token * @return bool @@ -176,7 +186,7 @@ public function authenticateToken($token) { try { /** @var AuthSession $session */ - $session = $this->tokenParser->getSession($token); + $session = $this->getTokenParser()->getSession($token); } catch (\Exception $e) { throw new AuthException(ErrorCode::AUTH_TOKEN_INVALID); } @@ -208,6 +218,7 @@ public function authenticateToken($token) throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,$err); } } + $this->setSession($session); return true; } diff --git a/src/Constants/ServiceConstants.php b/src/Constants/ServiceConstants.php index d215c92..dfc93aa 100644 --- a/src/Constants/ServiceConstants.php +++ b/src/Constants/ServiceConstants.php @@ -17,8 +17,6 @@ class ServiceConstants const AUTH_MANAGER = "AuthManager"; - const AUTH_ERROR_CODE_HELPER = "AuthErrorCodeHelper"; - const AUTH_USERS_SERVICE = "AuthUserService"; } \ No newline at end of file diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index ae9ca26..3819dec 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -14,6 +14,7 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; +use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Parser\AuthorizationHeaderParser; use Swoft\Bean\Annotation\Bean; use Swoft\Http\Message\Middleware\MiddlewareInterface; @@ -37,7 +38,7 @@ class AuthMiddleware implements MiddlewareInterface public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { /** @var AuthorizationHeaderParser $parser */ - $parser = App::getBean("AuthRequestHeaderParser"); + $parser = App::getBean(ServiceConstants::AUTH_REQUEST_HEADER_PARSER); $request = $parser->parse($request); $response = $handler->handle($request); return $response; diff --git a/src/Parser/AuthorizationHeaderParser.php b/src/Parser/AuthorizationHeaderParser.php index 0e19690..7089d8a 100644 --- a/src/Parser/AuthorizationHeaderParser.php +++ b/src/Parser/AuthorizationHeaderParser.php @@ -44,7 +44,7 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface $type = $this->getHeadString($authValue); if (isset($this->mergeTypes()[$type])) { /** @var AuthHandleInterface $handler */ - $handler = App::getBean($type); + $handler = App::getBean($this->mergeTypes()[$type]); $request = $handler->parse($request); } return $request; diff --git a/src/Parser/BasicAuthParser.php b/src/Parser/BasicAuthParser.php index f827710..0b9db22 100644 --- a/src/Parser/BasicAuthParser.php +++ b/src/Parser/BasicAuthParser.php @@ -13,7 +13,13 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Mapping\AuthHandleInterface; +use Swoft\Bean\Annotation\Bean; +/** + * Class BasicAuthParser + * @package Swoft\Auth\Parser + * @Bean() + */ class BasicAuthParser implements AuthHandleInterface { diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php index acd8cbb..cb320c4 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/BearerTokenParser.php @@ -13,12 +13,16 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\App; use Swoft\Auth\AuthManager; -use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Mapping\AuthHandleInterface; -use Swoft\Core\RequestContext; +use Swoft\Bean\Annotation\Bean; +/** + * Class BearerTokenParser + * @package Swoft\Auth\Parser + * @Bean() + */ class BearerTokenParser implements AuthHandleInterface { diff --git a/src/Parser/JWTTokenParser.php b/src/Parser/JWTTokenParser.php index 1af61df..086e7c5 100644 --- a/src/Parser/JWTTokenParser.php +++ b/src/Parser/JWTTokenParser.php @@ -11,11 +11,13 @@ use Firebase\JWT\JWT; use Swoft\Auth\Bean\AuthSession; +use Swoft\Bean\Annotation\Bean; use Swoft\Bean\Annotation\Value; /** * Class JWTTokenParser * @package App\Component\Acl\TokenParsers + * @Bean() */ class JWTTokenParser implements TokenParserInterface { From a88f43d7ec105eb5dd6ec4b3d28a1ce2ab3755e4 Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 21 May 2018 21:31:00 +0800 Subject: [PATCH 06/24] fix style --- composer.json | 3 +- src/AuthManager.php | 33 ++++++++----------- src/AuthUserService.php | 28 ++++++++-------- src/Bean/AuthResult.php | 15 +++++---- src/Bean/AuthSession.php | 15 ++++----- src/Bootstrap/CoreBean.php | 17 ++++------ src/Constants/AuthConstants.php | 15 ++++----- src/Constants/ServiceConstants.php | 22 ++++++------- src/Exception/AuthException.php | 17 +++++----- src/Helper/ErrorCode.php | 22 +++++++++---- src/Helper/ErrorCodeHelper.php | 16 ++++----- src/Mapping/AccountTypeInterface.php | 19 ++++++----- src/Mapping/AuthHandleInterface.php | 14 ++++---- src/Middleware/AclMiddleware.php | 23 ++++++------- src/Middleware/AuthMiddleware.php | 15 ++++----- src/Parser/AuthorizationHeaderParser.php | 18 +++++------ src/Parser/AuthorizationParserInterface.php | 16 ++++----- src/Parser/BasicAuthParser.php | 28 ++++++++-------- src/Parser/BearerTokenParser.php | 23 +++++++------ src/Parser/JWTTokenParser.php | 36 ++++++++++----------- src/Parser/TokenParserInterface.php | 16 ++++----- test/bootstrap.php | 11 +++++-- test/config/beans/base.php | 11 +++++-- test/config/beans/log.php | 36 +++++++++++++-------- test/config/define.php | 9 +++++- test/config/properties/app.php | 14 ++++++-- test/config/properties/cache.php | 22 +++++++++---- test/config/server.php | 8 +++++ 28 files changed, 277 insertions(+), 245 deletions(-) diff --git a/composer.json b/composer.json index 92cca52..110899b 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,8 @@ "require": { "swoft/http-server": "^1.0", "firebase/php-jwt": "^5.0", - "psr/simple-cache": "^1.0" + "psr/simple-cache": "^1.0", + "friendsofphp/php-cs-fixer": "^2.11" }, "autoload": { "psr-4": { diff --git a/src/AuthManager.php b/src/AuthManager.php index 69ed973..8233186 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -1,10 +1,11 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth; @@ -29,12 +30,11 @@ */ class AuthManager { - /** * @Value("${config.auth.cache.prefix}") * @var string */ - private $prefix = "token_"; + private $prefix = 'token_'; /** * @var int @@ -60,7 +60,6 @@ class AuthManager */ protected $tokenParser; - public function getSessionDuration() { return $this->sessionDuration; @@ -116,14 +115,13 @@ public function login(string $accountTypeName, array $data) try { $this->cache->set($this->getCacheKey($identity), $session->getToken(), $session->getExpirationTime()); } catch (InvalidArgumentException $e) { - $err = sprintf("%s 参数无效",$session->getIdentity()); - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,$err); + $err = sprintf('%s 参数无效', $session->getIdentity()); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, $err); } } return $session; } - protected function getCacheKey($identity) { return $this->prefix . $identity; @@ -168,10 +166,9 @@ public function getAccountType($name) return $account; } - - public function getTokenParser():TokenParserInterface + public function getTokenParser(): TokenParserInterface { - if(empty($this->tokenParser)){ + if (empty($this->tokenParser)) { $this->tokenParser = App::getBean(JWTTokenParser::class); } return $this->tokenParser; @@ -214,14 +211,12 @@ public function authenticateToken($token) throw new AuthException(ErrorCode::AUTH_TOKEN_INVALID); } } catch (InvalidArgumentException $e) { - $err = sprintf("%s 参数无效",$session->getIdentity()); - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,$err); + $err = sprintf('%s 参数无效', $session->getIdentity()); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, $err); } } $this->setSession($session); return true; } - - -} \ No newline at end of file +} diff --git a/src/AuthUserService.php b/src/AuthUserService.php index bb70049..dfe77db 100644 --- a/src/AuthUserService.php +++ b/src/AuthUserService.php @@ -1,35 +1,36 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth; - use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Constants\AuthConstants; use Swoft\Core\RequestContext; +/** + * Class AuthUserService + * @package Swoft\Auth + */ class AuthUserService { - - public function getUserIdentity(): string { - if(!$this->getSession()){ + if (!$this->getSession()) { return ''; } return $this->getSession()->getIdentity() ?? ''; } - public function getUserExtendData(): array { - if(!$this->getSession()){ + if (!$this->getSession()) { return []; } return $this->getSession()->getExtendedData() ?? []; @@ -48,7 +49,7 @@ public function getSession() * @param string $action 方法名 * @return bool */ - public function auth(string $controller,string $action): bool + public function auth(string $controller, string $action): bool { $id = $this->getUserIdentity(); if ($id) { @@ -56,5 +57,4 @@ public function auth(string $controller,string $action): bool } return false; } - -} \ No newline at end of file +} diff --git a/src/Bean/AuthResult.php b/src/Bean/AuthResult.php index 11e9e1f..f484fa9 100644 --- a/src/Bean/AuthResult.php +++ b/src/Bean/AuthResult.php @@ -1,9 +1,11 @@ extendedData = $extendedData; return $this; } - - -} \ No newline at end of file +} diff --git a/src/Bean/AuthSession.php b/src/Bean/AuthSession.php index 0557e63..e927d69 100644 --- a/src/Bean/AuthSession.php +++ b/src/Bean/AuthSession.php @@ -1,10 +1,11 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Bean; @@ -156,6 +157,4 @@ public function setExtendedData(array $extendedData) $this->extendedData = $extendedData; return $this; } - - -} \ No newline at end of file +} diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index 26e026c..cefd061 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -1,20 +1,18 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Bootstrap; use Swoft\Auth\AuthManager; -use Swoft\Auth\AuthUserService; use Swoft\Auth\Constants\ServiceConstants; -use Swoft\Auth\Helper\ErrorCodeHelper; use Swoft\Auth\Parser\AuthorizationHeaderParser; -use Swoft\Auth\Parser\RequestHeaderParser; use Swoft\Bean\Annotation\BootBean; use Swoft\Core\BootBeanInterface; @@ -25,7 +23,6 @@ */ class CoreBean implements BootBeanInterface { - /** * @return array */ @@ -40,4 +37,4 @@ public function beans() ] ]; } -} \ No newline at end of file +} diff --git a/src/Constants/AuthConstants.php b/src/Constants/AuthConstants.php index 55350bb..c22e858 100644 --- a/src/Constants/AuthConstants.php +++ b/src/Constants/AuthConstants.php @@ -1,16 +1,16 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Constants; class AuthConstants { - const HEADER_KEY = 'Authorization'; const BASIC_USER_NAME = 'basicUsername'; @@ -24,5 +24,4 @@ class AuthConstants const IDENTITY = 'identity'; const EXTEND_DATA = 'extendedData'; - -} \ No newline at end of file +} diff --git a/src/Constants/ServiceConstants.php b/src/Constants/ServiceConstants.php index dfc93aa..30c42f9 100644 --- a/src/Constants/ServiceConstants.php +++ b/src/Constants/ServiceConstants.php @@ -1,22 +1,20 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Constants; - class ServiceConstants { + const AUTH_REQUEST_HEADER_PARSER = 'AuthRequestHeaderParser'; - const AUTH_REQUEST_HEADER_PARSER = "AuthRequestHeaderParser"; - - const AUTH_MANAGER = "AuthManager"; - - const AUTH_USERS_SERVICE = "AuthUserService"; + const AUTH_MANAGER = 'AuthManager'; -} \ No newline at end of file + const AUTH_USERS_SERVICE = 'AuthUserService'; +} diff --git a/src/Exception/AuthException.php b/src/Exception/AuthException.php index 848d109..0f8b705 100644 --- a/src/Exception/AuthException.php +++ b/src/Exception/AuthException.php @@ -1,10 +1,11 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Exception; @@ -14,10 +15,8 @@ class AuthException extends RuntimeException { - - public function __construct(int $code = 0, string $message = "", Throwable $previous = null) + public function __construct(int $code = 0, string $message = '', Throwable $previous = null) { parent::__construct($message, $code, $previous); } - -} \ No newline at end of file +} diff --git a/src/Helper/ErrorCode.php b/src/Helper/ErrorCode.php index dcf3cbe..8fc9961 100644 --- a/src/Helper/ErrorCode.php +++ b/src/Helper/ErrorCode.php @@ -1,10 +1,11 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Helper; @@ -23,16 +24,22 @@ class ErrorCode * 通用 */ const GENERAL_SYSTEM = 1010; + const GENERAL_NOT_IMPLEMENTED = 1020; + const GENERAL_NOT_FOUND = 1030; /** * 用户认证 */ const AUTH_INVALID_ACCOUNT_TYPE = 2010; + const AUTH_LOGIN_FAILED = 2020; + const AUTH_TOKEN_INVALID = 2030; + const AUTH_SESSION_EXPIRED = 2040; + const AUTH_SESSION_INVALID = 2050; /** @@ -44,12 +51,13 @@ class ErrorCode * 客户端错误 */ const DATA_FAILED = 4010; + const DATA_NOT_FOUND = 4020; /** * 服务器错误 */ const POST_DATA_NOT_PROVIDED = 5010; - const POST_DATA_INVALID = 5020; -} \ No newline at end of file + const POST_DATA_INVALID = 5020; +} diff --git a/src/Helper/ErrorCodeHelper.php b/src/Helper/ErrorCodeHelper.php index b71aa1c..d60d26d 100644 --- a/src/Helper/ErrorCodeHelper.php +++ b/src/Helper/ErrorCodeHelper.php @@ -1,10 +1,11 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Helper; @@ -18,7 +19,6 @@ */ class ErrorCodeHelper { - /** * @var array */ @@ -133,6 +133,4 @@ public function getErrors() { return $this->errors; } - - -} \ No newline at end of file +} diff --git a/src/Mapping/AccountTypeInterface.php b/src/Mapping/AccountTypeInterface.php index e19c693..099a744 100644 --- a/src/Mapping/AccountTypeInterface.php +++ b/src/Mapping/AccountTypeInterface.php @@ -1,22 +1,22 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Mapping; @@ -18,5 +19,4 @@ interface AuthHandleInterface * @return \Psr\Http\Message\ServerRequestInterface */ public function parse(ServerRequestInterface $request): ServerRequestInterface; - -} \ No newline at end of file +} diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 1403514..9076c50 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -1,15 +1,15 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Middleware; - use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -28,7 +28,6 @@ */ class AclMiddleware implements MiddlewareInterface { - /** * Process an incoming server request and return a response, optionally delegating * response creation to a handler. @@ -42,10 +41,9 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; $handlerArray = self::getHandlerArray($requestHandler); if ($requestHandler && is_array($handlerArray)) { - - if(!App::hasBean(ServiceConstants::AUTH_USERS_SERVICE)){ - $error = sprintf("need AuthUserService %s",$requestHandler); - throw new AuthException(ErrorCode::POST_DATA_INVALID,$error); + if (!App::hasBean(ServiceConstants::AUTH_USERS_SERVICE)) { + $error = sprintf('need AuthUserService %s', $requestHandler); + throw new AuthException(ErrorCode::POST_DATA_INVALID, $error); } /** @var AuthUserService $service */ $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); @@ -70,5 +68,4 @@ public static function getHandlerArray(string $handler) } return $segments; } - -} \ No newline at end of file +} diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index 3819dec..41ab33e 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -1,15 +1,15 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Middleware; - use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -26,7 +26,6 @@ */ class AuthMiddleware implements MiddlewareInterface { - /** * Process an incoming server request and return a response, optionally delegating * response creation to a handler. @@ -43,4 +42,4 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $response = $handler->handle($request); return $response; } -} \ No newline at end of file +} diff --git a/src/Parser/AuthorizationHeaderParser.php b/src/Parser/AuthorizationHeaderParser.php index 7089d8a..3b4493e 100644 --- a/src/Parser/AuthorizationHeaderParser.php +++ b/src/Parser/AuthorizationHeaderParser.php @@ -1,10 +1,11 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Parser; @@ -50,13 +51,11 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface return $request; } - private function getHeadString(string $val):string { - return explode(' ',$val)[0] ?? ''; + return explode(' ', $val)[0] ?? ''; } - private function mergeTypes(): array { if (empty($this->authTypes)) { @@ -65,7 +64,6 @@ private function mergeTypes(): array return $this->authTypes; } - public function defaultTypes(): array { return [ @@ -73,4 +71,4 @@ public function defaultTypes(): array BasicAuthParser::NAME => BasicAuthParser::class ]; } -} \ No newline at end of file +} diff --git a/src/Parser/AuthorizationParserInterface.php b/src/Parser/AuthorizationParserInterface.php index 9c9ef9e..2160468 100644 --- a/src/Parser/AuthorizationParserInterface.php +++ b/src/Parser/AuthorizationParserInterface.php @@ -1,20 +1,18 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Parser; - use Psr\Http\Message\ServerRequestInterface; interface AuthorizationParserInterface { - public function parse(ServerRequestInterface $request); - -} \ No newline at end of file +} diff --git a/src/Parser/BasicAuthParser.php b/src/Parser/BasicAuthParser.php index 0b9db22..cf9a03a 100644 --- a/src/Parser/BasicAuthParser.php +++ b/src/Parser/BasicAuthParser.php @@ -1,15 +1,15 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Parser; - use Psr\Http\Message\ServerRequestInterface; use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Mapping\AuthHandleInterface; @@ -22,7 +22,6 @@ */ class BasicAuthParser implements AuthHandleInterface { - const NAME = 'Basic'; /** @@ -33,10 +32,10 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface { $authHeader = $request->getHeaderLine(AuthConstants::HEADER_KEY) ?? ''; $basic = $this->parseValue($authHeader); - if($basic){ + if ($basic) { $request = $request - ->withAttribute(AuthConstants::BASIC_USER_NAME,$this->getUsername($basic)) - ->withAttribute(AuthConstants::BASIC_PASSWORD,$this->getPassword($basic)); + ->withAttribute(AuthConstants::BASIC_USER_NAME, $this->getUsername($basic)) + ->withAttribute(AuthConstants::BASIC_PASSWORD, $this->getPassword($basic)); } return $request; } @@ -46,7 +45,8 @@ protected function getUsername(array $basic) return $basic[0]??''; } - protected function getPassword(array $basic){ + protected function getPassword(array $basic) + { return $basic[1]??''; } @@ -56,9 +56,9 @@ protected function parseValue($string):array return null; } $val = preg_replace('/.*\s/', '', $string); - if(!$val){ + if (!$val) { return null; } - return explode(':',base64_decode($val)); + return explode(':', base64_decode($val)); } -} \ No newline at end of file +} diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php index cb320c4..ad492ef 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/BearerTokenParser.php @@ -1,15 +1,15 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Parser; - use Psr\Http\Message\ServerRequestInterface; use Swoft\App; use Swoft\Auth\AuthManager; @@ -25,7 +25,6 @@ */ class BearerTokenParser implements AuthHandleInterface { - const NAME = 'Bearer'; /** @@ -37,9 +36,9 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface $token = $this->getToken($request); /** @var AuthManager $manager */ $manager = App::getBean(ServiceConstants::AUTH_MANAGER); - if($token){ + if ($token) { $res = $manager->authenticateToken($token); - $request = $request->withAttribute(AuthConstants::IS_LOGIN,$res); + $request = $request->withAttribute(AuthConstants::IS_LOGIN, $res); } return $request; } @@ -51,11 +50,11 @@ protected function getToken(ServerRequestInterface $request) return $authQuery ? $authQuery : $this->parseValue($authHeader); } - protected function parseValue($string){ + protected function parseValue($string) + { if (strpos(trim($string), self::NAME) !== 0) { return null; } return preg_replace('/.*\s/', '', $string); } - -} \ No newline at end of file +} diff --git a/src/Parser/JWTTokenParser.php b/src/Parser/JWTTokenParser.php index 086e7c5..c7f3536 100644 --- a/src/Parser/JWTTokenParser.php +++ b/src/Parser/JWTTokenParser.php @@ -1,14 +1,15 @@ setExtendedData($tokenData->data); } - protected function create(string $issuer, string $user, int $iat,int $exp,array $data):array + protected function create(string $issuer, string $user, int $iat, int $exp, array $data):array { - return [ /* The iss (issuer) claim identifies the principal @@ -82,7 +84,7 @@ protected function create(string $issuer, string $user, int $iat,int $exp,array The iss value is a case-sensitive string containing a StringOrURI value. Use of this claim is OPTIONAL. ------------------------------------------------*/ - "iss" => $issuer, + 'iss' => $issuer, /* The sub (subject) claim identifies the principal @@ -95,7 +97,7 @@ protected function create(string $issuer, string $user, int $iat,int $exp,array is a case-sensitive string containing a StringOrURI value. Use of this claim is OPTIONAL. ------------------------------------------------*/ - "sub" => $user, + 'sub' => $user, /* The iat (issued at) claim identifies the time at @@ -104,7 +106,7 @@ protected function create(string $issuer, string $user, int $iat,int $exp,array be a number containing a NumericDate value. Use of this claim is OPTIONAL. ------------------------------------------------*/ - "iat" => $iat, + 'iat' => $iat, /* The exp (expiration time) claim identifies the @@ -118,26 +120,22 @@ protected function create(string $issuer, string $user, int $iat,int $exp,array number containing a NumericDate value. Use of this claim is OPTIONAL. ------------------------------------------------*/ - "exp" => $exp, + 'exp' => $exp, /* Expand data ------------------------------------------------*/ - "data" => $data, + 'data' => $data, ]; } - public function encode($token): string { return (string)JWT::encode($token, $this->secret, $this->algorithm); } - public function decode($token) { return JWT::decode($token, $this->secret, [$this->algorithm]); } - - -} \ No newline at end of file +} diff --git a/src/Parser/TokenParserInterface.php b/src/Parser/TokenParserInterface.php index bf1e4bf..7011652 100644 --- a/src/Parser/TokenParserInterface.php +++ b/src/Parser/TokenParserInterface.php @@ -1,15 +1,15 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Parser; - use Swoft\Auth\Bean\AuthSession; interface TokenParserInterface @@ -25,6 +25,4 @@ public function getToken(AuthSession $session):string ; * @return AuthSession */ public function getSession(string $token):AuthSession ; - - -} \ No newline at end of file +} diff --git a/test/bootstrap.php b/test/bootstrap.php index 83e1718..e001879 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -1,5 +1,12 @@ init(); - - diff --git a/test/config/beans/base.php b/test/config/beans/base.php index b993871..6a1ce8d 100644 --- a/test/config/beans/base.php +++ b/test/config/beans/base.php @@ -1,3 +1,10 @@ [ - "class" => \Swoft\Log\FileHandler::class, - "logFile" => "@runtime/logs/notice.log", + 'noticeHandler' => [ + 'class' => \Swoft\Log\FileHandler::class, + 'logFile' => '@runtime/logs/notice.log', 'formatter' => '${lineFormatter}', - "levels" => [ + 'levels' => [ \Swoft\Log\Logger::NOTICE, \Swoft\Log\Logger::INFO, \Swoft\Log\Logger::DEBUG, \Swoft\Log\Logger::TRACE, ] ], - "applicationHandler" => [ - "class" => \Swoft\Log\FileHandler::class, - "logFile" => "@runtime/logs/error.log", + 'applicationHandler' => [ + 'class' => \Swoft\Log\FileHandler::class, + 'logFile' => '@runtime/logs/error.log', 'formatter' => '${lineFormatter}', - "levels" => [ + 'levels' => [ \Swoft\Log\Logger::ERROR, \Swoft\Log\Logger::WARNING ] ], - "logger" => [ - "class" => \Swoft\Log\Logger::class, - "name" => APP_NAME, - "flushInterval" => 100, - "flushRequest" => true, - "handlers" => [ + 'logger' => [ + 'class' => \Swoft\Log\Logger::class, + 'name' => APP_NAME, + 'flushInterval' => 100, + 'flushRequest' => true, + 'handlers' => [ '${noticeHandler}', '${applicationHandler}' ] diff --git a/test/config/define.php b/test/config/define.php index e18d417..410c414 100644 --- a/test/config/define.php +++ b/test/config/define.php @@ -1,5 +1,12 @@ '1.0', + 'version' => '1.0', 'autoInitBean' => true, 'beanScan' => [ - 'Swoft\\Http\\Server\\Test\\Testing' => BASE_PATH."/Testing" + 'Swoft\\Http\\Server\\Test\\Testing' => BASE_PATH.'/Testing' ], 'I18n' => [ 'sourceLanguage' => '@root/resources/messages/', @@ -17,5 +25,5 @@ 'timeout' => 3000 ] ], - 'cache' => require dirname(__FILE__) . DS . "cache.php", + 'cache' => require dirname(__FILE__) . DS . 'cache.php', ]; diff --git a/test/config/properties/cache.php b/test/config/properties/cache.php index 30c0bce..ddc2d61 100644 --- a/test/config/properties/cache.php +++ b/test/config/properties/cache.php @@ -1,17 +1,25 @@ [ 'name' => 'redis1', - "uri" => [ + 'uri' => [ '127.0.0.1:1111', '127.0.0.1:1111', ], - "maxIdel" => 1, - "maxActive" => 1, - "maxWait" => 1, - "timeout" => 1, - "balancer" => 'random1', - "useProvider" => true, + 'maxIdel' => 1, + 'maxActive' => 1, + 'maxWait' => 1, + 'timeout' => 1, + 'balancer' => 'random1', + 'useProvider' => true, 'provider' => 'consul1', ], ]; diff --git a/test/config/server.php b/test/config/server.php index b83d552..26030c8 100644 --- a/test/config/server.php +++ b/test/config/server.php @@ -1,4 +1,12 @@ [ 'pfile' => env('PFILE', '/tmp/swoft.pid'), From fa6d10aadc54f7fe373d99a3cf7a3dca4171f920 Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 21 May 2018 21:45:16 +0800 Subject: [PATCH 07/24] add test --- test/Cases/AbstractTestCase.php | 203 ++++++++++++++++++++ test/Cases/AuthManagerTest.php | 19 ++ test/Cases/AuthUserServiceTest.php | 22 +++ test/Cases/Helper/ErrorCodeHelperTest.php | 17 ++ test/Cases/Middleware/AclMiddlewareTest.php | 17 ++ test/Cases/Parser/BasicAuthParserTest.php | 17 ++ 6 files changed, 295 insertions(+) create mode 100644 test/Cases/AbstractTestCase.php create mode 100644 test/Cases/AuthManagerTest.php create mode 100644 test/Cases/AuthUserServiceTest.php create mode 100644 test/Cases/Helper/ErrorCodeHelperTest.php create mode 100644 test/Cases/Middleware/AclMiddlewareTest.php create mode 100644 test/Cases/Parser/BasicAuthParserTest.php diff --git a/test/Cases/AbstractTestCase.php b/test/Cases/AbstractTestCase.php new file mode 100644 index 0000000..ab16bd0 --- /dev/null +++ b/test/Cases/AbstractTestCase.php @@ -0,0 +1,203 @@ +buildMockRequest($method, $uri, $parameters, $accept, $swooleRequest, $headers); + + $swooleRequest->setRawContent($rawContent); + + $request = Request::loadFromSwooleRequest($swooleRequest); + $response = new Response($swooleResponse); + + /** @var \Swoft\Http\Server\ServerDispatcher $dispatcher */ + $dispatcher = App::getBean('serverDispatcher'); + return $dispatcher->dispatch($request, $response); + } + + /** + * Send a mock json request + * + * @param string $method + * @param string $uri + * @param array $parameters + * @param array $headers + * @param string $rawContent + * @return bool|\Swoft\Http\Message\Testing\Web\Response + */ + public function json( + string $method, + string $uri, + array $parameters = [], + array $headers = [], + string $rawContent = '' + ) { + return $this->request($method, $uri, $parameters, self::ACCEPT_JSON, $headers, $rawContent); + } + + /** + * Send a mock view request + * + * @param string $method + * @param string $uri + * @param array $parameters + * @param array $headers + * @param string $rawContent + * @return bool|\Swoft\Http\Message\Testing\Web\Response + */ + public function view( + string $method, + string $uri, + array $parameters = [], + array $headers = [], + string $rawContent = '' + ) { + return $this->request($method, $uri, $parameters, self::ACCEPT_VIEW, $headers, $rawContent); + } + + /** + * Send a mock raw content request + * + * @param string $method + * @param string $uri + * @param array $parameters + * @param array $headers + * @param string $rawContent + * @return bool|\Swoft\Http\Message\Testing\Web\Response + */ + public function raw( + string $method, + string $uri, + array $parameters = [], + array $headers = [], + string $rawContent = '' + ) { + return $this->request($method, $uri, $parameters, self::ACCEPT_RAW, $headers, $rawContent); + } + + /** + * @param string $method + * @param string $uri + * @param array $parameters + * @param string $accept + * @param \Swoole\Http\Request $swooleRequest + * @param array $headers + */ + protected function buildMockRequest( + string $method, + string $uri, + array $parameters, + string $accept, + &$swooleRequest, + array $headers = [] + ) { + $urlAry = parse_url($uri); + $urlParams = []; + if (isset($urlAry['query'])) { + parse_str($urlAry['query'], $urlParams); + } + $defaultHeaders = [ + 'host' => '127.0.0.1', + 'connection' => 'keep-alive', + 'cache-control' => 'max-age=0', + 'user-agent' => 'PHPUnit', + 'upgrade-insecure-requests' => '1', + 'accept' => $accept, + 'dnt' => '1', + 'accept-encoding' => 'gzip, deflate, br', + 'accept-language' => 'zh-CN,zh;q=0.8,en;q=0.6,it-IT;q=0.4,it;q=0.2', + ]; + + $swooleRequest->fd = 1; + $swooleRequest->header = ArrayHelper::merge($headers, $defaultHeaders); + $swooleRequest->server = [ + 'request_method' => $method, + 'request_uri' => $uri, + 'path_info' => '/', + 'request_time' => microtime(), + 'request_time_float' => microtime(true), + 'server_port' => 80, + 'remote_port' => 54235, + 'remote_addr' => '10.0.2.2', + 'master_time' => microtime(), + 'server_protocol' => 'HTTP/1.1', + 'server_software' => 'swoole-http-server', + ]; + + if ($method == 'GET') { + $swooleRequest->get = $parameters; + } elseif ($method == 'POST') { + $swooleRequest->post = $parameters; + } + + if (! empty($urlParams)) { + $get = empty($swooleRequest->get) ? [] : $swooleRequest->get; + $swooleRequest->get = array_merge($urlParams, $get); + } + } + + protected function tearDown() + { + parent::tearDown(); + swoole_timer_after(1 * 1000, function () { + swoole_event_exit(); + }); + } + + protected function setCoName($name): String + { + $name = "{$name}-co"; + + return $name; + } +} diff --git a/test/Cases/AuthManagerTest.php b/test/Cases/AuthManagerTest.php new file mode 100644 index 0000000..b49733f --- /dev/null +++ b/test/Cases/AuthManagerTest.php @@ -0,0 +1,19 @@ + Date: Mon, 21 May 2018 21:54:33 +0800 Subject: [PATCH 08/24] README --- README.md | 10 ++++++---- test/Cases/AuthManagerTest.php | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6ff994f..34130eb 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,13 @@ composer require swoft/auth ## Document -- BasicAuth -- BearerToken -- JWT +now +- BasicAuth +- BearerToken (JWT) - Acl -- CodeHelper + +feature +- oauth 2.0 ```php diff --git a/test/Cases/AuthManagerTest.php b/test/Cases/AuthManagerTest.php index b49733f..2035f12 100644 --- a/test/Cases/AuthManagerTest.php +++ b/test/Cases/AuthManagerTest.php @@ -16,4 +16,6 @@ */ class AuthManagerTest extends AbstractTestCase { + + } From 826b70817fabd07a502406fe405c558f99d0dd28 Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 21 May 2018 21:56:22 +0800 Subject: [PATCH 09/24] README --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 34130eb..086fdc2 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,18 @@ Swoft Auth Component composer require swoft/auth ``` -## Document +## Document [wiki](https://github.com/aprchen/swoft-auth/wiki) now -- BasicAuth +- BasicAuth - BearerToken (JWT) - Acl feature - oauth 2.0 -```php -``` - ## Unit testing ```bash From 35311c0a76e7e09e47538d08e45087902eb0c1a5 Mon Sep 17 00:00:00 2001 From: ott321 Date: Tue, 22 May 2018 15:18:38 +0800 Subject: [PATCH 10/24] finished --- src/AuthManager.php | 34 ++++++++++++++++------------- src/AuthUserService.php | 37 ++++++++++++++++++++++++++------ src/Bean/AuthSession.php | 8 +++---- src/Bootstrap/CoreBean.php | 3 --- src/Middleware/AclMiddleware.php | 33 ++++++++-------------------- src/Parser/JWTTokenParser.php | 4 ++-- 6 files changed, 64 insertions(+), 55 deletions(-) diff --git a/src/AuthManager.php b/src/AuthManager.php index 8233186..51b8395 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -31,31 +31,26 @@ class AuthManager { /** - * @Value("${config.auth.cache.prefix}") * @var string */ - private $prefix = 'token_'; + protected $prefix = 'swoft.token.'; /** * @var int - * @Value("${config.auth.token.lifetime}") */ protected $sessionDuration = 86400; /** * @var bool - * @Value("${config.auth.cache.enable}") */ protected $cacheEnable = false; /** - * @Value("${config.auth.cache}") * @var CacheInterface */ protected $cache; /** - * @Value("${config.auth.token.parser}") * @var TokenParserInterface */ protected $tokenParser; @@ -103,19 +98,21 @@ public function login(string $accountTypeName, array $data) if (!$account = $this->getAccountType($accountTypeName)) { throw new AuthException(ErrorCode::AUTH_INVALID_ACCOUNT_TYPE); } - /** @var AuthResult $result */ $result = $account->login($data); - if (!$result) { + if (!$result instanceof AuthResult || $result->getIdentity() == '') { throw new AuthException(ErrorCode::AUTH_LOGIN_FAILED); } - $identity = $result->getIdentity(); - $session = $this->generateSession($accountTypeName, $identity, $data); + $session = $this->generateSession($accountTypeName, $result->getIdentity(), $result->getExtendedData()); $this->setSession($session); if ($this->cacheEnable === true) { try { - $this->cache->set($this->getCacheKey($identity), $session->getToken(), $session->getExpirationTime()); + $this->getCacheClient()->set( + $this->getCacheKey($result->getIdentity()), + $session->getToken(), + $session->getExpirationTime() + ); } catch (InvalidArgumentException $e) { - $err = sprintf('%s 参数无效', $session->getIdentity()); + $err = sprintf('%s 参数无效,message : %s', $session->getIdentity(),$e->getMessage()); throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, $err); } } @@ -168,12 +165,19 @@ public function getAccountType($name) public function getTokenParser(): TokenParserInterface { - if (empty($this->tokenParser)) { + if (!$this->tokenParser instanceof TokenParserInterface) { $this->tokenParser = App::getBean(JWTTokenParser::class); } return $this->tokenParser; } + public function getCacheClient(){ + if(!$this->cache instanceof CacheInterface){ + throw new AuthException(ErrorCode::POST_DATA_INVALID,"AuthManager need cache client"); + } + return $this->cache; + } + /** * @param $token * @return bool @@ -206,12 +210,12 @@ public function authenticateToken($token) if ($this->cacheEnable === true) { try { - $cache = $this->cache->get($this->getCacheKey($session->getIdentity())); + $cache = $this->getCacheClient()->get($this->getCacheKey($session->getIdentity())); if (!$cache || $cache !== $token) { throw new AuthException(ErrorCode::AUTH_TOKEN_INVALID); } } catch (InvalidArgumentException $e) { - $err = sprintf('%s 参数无效', $session->getIdentity()); + $err = sprintf('%s 参数无效,message : %s', $session->getIdentity(),$e->getMessage()); throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, $err); } } diff --git a/src/AuthUserService.php b/src/AuthUserService.php index dfe77db..3facc45 100644 --- a/src/AuthUserService.php +++ b/src/AuthUserService.php @@ -10,8 +10,11 @@ namespace Swoft\Auth; +use Psr\Http\Message\ServerRequestInterface; use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Constants\AuthConstants; +use Swoft\Auth\Exception\AuthException; +use Swoft\Auth\Helper\ErrorCode; use Swoft\Core\RequestContext; /** @@ -45,16 +48,36 @@ public function getSession() } /** - * @param string $controller 控制器名 - * @param string $action 方法名 + * + * $controller = $this->getHandlerArray($requestHandler)[0]; + * $method = $this->getHandlerArray($requestHandler)[1]; + * $id = $this->getUserIdentity(); + * if ($id) { + * return true; + * } + * return false; + * + * + * @param string $requestHandler + * @param ServerRequestInterface $request * @return bool */ - public function auth(string $controller, string $action): bool + public function auth(string $requestHandler, ServerRequestInterface $request): bool { - $id = $this->getUserIdentity(); - if ($id) { - return true; + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,"you need copy AuthUserService::auth method"); + } + + /** + * @param string $handler + * @return array|null + */ + protected function getHandlerArray(string $handler) + { + $segments = explode('@', trim($handler)); + if (!isset($segments[1])) { + return null; } - return false; + return $segments; } + } diff --git a/src/Bean/AuthSession.php b/src/Bean/AuthSession.php index e927d69..ed0306c 100644 --- a/src/Bean/AuthSession.php +++ b/src/Bean/AuthSession.php @@ -48,7 +48,7 @@ class AuthSession /** * @var array Expand data, define it yourself */ - protected $extendedData=[]; + protected $extendedData=null; /** * @return string @@ -143,16 +143,16 @@ public function setExpirationTime(int $expirationTime) /** * @return array */ - public function getExtendedData(): array + public function getExtendedData() { return $this->extendedData; } /** - * @param array $extendedData + * @param $extendedData * @return AuthSession */ - public function setExtendedData(array $extendedData) + public function setExtendedData($extendedData) { $this->extendedData = $extendedData; return $this; diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index cefd061..1792cf3 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -32,9 +32,6 @@ public function beans() ServiceConstants::AUTH_REQUEST_HEADER_PARSER => [ 'class' => AuthorizationHeaderParser::class ], - ServiceConstants::AUTH_MANAGER => [ - 'class' => AuthManager::class - ] ]; } } diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 9076c50..245abe7 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -39,33 +39,18 @@ class AclMiddleware implements MiddlewareInterface public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; - $handlerArray = self::getHandlerArray($requestHandler); - if ($requestHandler && is_array($handlerArray)) { - if (!App::hasBean(ServiceConstants::AUTH_USERS_SERVICE)) { - $error = sprintf('need AuthUserService %s', $requestHandler); - throw new AuthException(ErrorCode::POST_DATA_INVALID, $error); - } - /** @var AuthUserService $service */ - $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); - $flag = $service->auth($handlerArray[0], $handlerArray[1]); - if (!$flag) { - throw new AuthException(ErrorCode::ACCESS_DENIED); - } + if (!App::hasBean(ServiceConstants::AUTH_USERS_SERVICE)) { + $error = sprintf('need AuthUserService %s', $requestHandler); + throw new AuthException(ErrorCode::POST_DATA_INVALID, $error); + } + /** @var AuthUserService $service */ + $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); + $flag = $service->auth($requestHandler,$request); + if (!$flag) { + throw new AuthException(ErrorCode::ACCESS_DENIED); } $response = $handler->handle($request); return $response; } - /** - * @param string $handler - * @return array|null - */ - public static function getHandlerArray(string $handler) - { - $segments = explode('@', trim($handler)); - if (!isset($segments[1])) { - return null; - } - return $segments; - } } diff --git a/src/Parser/JWTTokenParser.php b/src/Parser/JWTTokenParser.php index c7f3536..f6ae94e 100644 --- a/src/Parser/JWTTokenParser.php +++ b/src/Parser/JWTTokenParser.php @@ -31,13 +31,13 @@ class JWTTokenParser implements TokenParserInterface const ALGORITHM_RS256 = 'RS256'; /** - * @Value("${config.auth.algorithm}") + * @Value("${config.auth.jwt.algorithm}") * @var string */ protected $algorithm=self::ALGORITHM_HS256; /** - * @Value("${config.auth.secret}") + * @Value("${config.auth.jwt.secret}") * @var string */ protected $secret='swoft'; From 19a7e7c868673e617138f19a031d707d733ffa4b Mon Sep 17 00:00:00 2001 From: ott321 Date: Tue, 22 May 2018 21:40:03 +0800 Subject: [PATCH 11/24] add interface and config --- src/AuthManager.php | 10 +++--- src/AuthUserService.php | 3 +- src/Mapping/AuthManagerInterface.php | 31 ++++++++++++++++ src/Mapping/AuthServiceInterface.php | 35 +++++++++++++++++++ .../AuthorizationParserInterface.php | 2 +- .../TokenParserInterface.php | 2 +- src/Middleware/AclMiddleware.php | 19 ++++++---- src/Parser/BearerTokenParser.php | 19 ++++++++-- src/Parser/JWTTokenParser.php | 1 + 9 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 src/Mapping/AuthManagerInterface.php create mode 100644 src/Mapping/AuthServiceInterface.php rename src/{Parser => Mapping}/AuthorizationParserInterface.php (92%) rename src/{Parser => Mapping}/TokenParserInterface.php (94%) diff --git a/src/AuthManager.php b/src/AuthManager.php index 51b8395..10c6093 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -19,16 +19,16 @@ use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AccountTypeInterface; +use Swoft\Auth\Mapping\AuthManagerInterface; +use Swoft\Auth\Mapping\TokenParserInterface; use Swoft\Auth\Parser\JWTTokenParser; -use Swoft\Auth\Parser\TokenParserInterface; -use Swoft\Bean\Annotation\Value; use Swoft\Core\RequestContext; /** * Class AuthManager * @package Swoft\Auth */ -class AuthManager +class AuthManager implements AuthManagerInterface { /** * @var string @@ -93,7 +93,7 @@ public function loggedIn() * @param array $data * @return AuthSession */ - public function login(string $accountTypeName, array $data) + public function login(string $accountTypeName, array $data):AuthSession { if (!$account = $this->getAccountType($accountTypeName)) { throw new AuthException(ErrorCode::AUTH_INVALID_ACCOUNT_TYPE); @@ -183,7 +183,7 @@ public function getCacheClient(){ * @return bool * @throws AuthException */ - public function authenticateToken($token) + public function authenticateToken(string $token):bool { try { /** @var AuthSession $session */ diff --git a/src/AuthUserService.php b/src/AuthUserService.php index 3facc45..0faf2d5 100644 --- a/src/AuthUserService.php +++ b/src/AuthUserService.php @@ -15,13 +15,14 @@ use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; +use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Core\RequestContext; /** * Class AuthUserService * @package Swoft\Auth */ -class AuthUserService +class AuthUserService implements AuthServiceInterface { public function getUserIdentity(): string { diff --git a/src/Mapping/AuthManagerInterface.php b/src/Mapping/AuthManagerInterface.php new file mode 100644 index 0000000..1d840bb --- /dev/null +++ b/src/Mapping/AuthManagerInterface.php @@ -0,0 +1,31 @@ + + */ + +namespace Swoft\Auth\Mapping; + + +use Swoft\Auth\Bean\AuthSession; + +interface AuthManagerInterface +{ + + /** + * @param $accountTypeName + * @param array $data + * @return AuthSession + */ + public function login(string $accountTypeName, array $data):AuthSession; + + /** + * @param $token + * @return bool + */ + public function authenticateToken(string $token):bool ; + +} \ No newline at end of file diff --git a/src/Mapping/AuthServiceInterface.php b/src/Mapping/AuthServiceInterface.php new file mode 100644 index 0000000..7d2dcdd --- /dev/null +++ b/src/Mapping/AuthServiceInterface.php @@ -0,0 +1,35 @@ + + */ + +namespace Swoft\Auth\Mapping; + + +use Psr\Http\Message\ServerRequestInterface; + +interface AuthServiceInterface +{ + + /** + * + * $controller = $this->getHandlerArray($requestHandler)[0]; + * $method = $this->getHandlerArray($requestHandler)[1]; + * $id = $this->getUserIdentity(); + * if ($id) { + * return true; + * } + * return false; + * + * + * @param string $requestHandler + * @param ServerRequestInterface $request + * @return bool + */ + public function auth(string $requestHandler, ServerRequestInterface $request): bool; + +} \ No newline at end of file diff --git a/src/Parser/AuthorizationParserInterface.php b/src/Mapping/AuthorizationParserInterface.php similarity index 92% rename from src/Parser/AuthorizationParserInterface.php rename to src/Mapping/AuthorizationParserInterface.php index 2160468..f40e6b7 100644 --- a/src/Parser/AuthorizationParserInterface.php +++ b/src/Mapping/AuthorizationParserInterface.php @@ -8,7 +8,7 @@ * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ -namespace Swoft\Auth\Parser; +namespace Swoft\Auth\Mapping; use Psr\Http\Message\ServerRequestInterface; diff --git a/src/Parser/TokenParserInterface.php b/src/Mapping/TokenParserInterface.php similarity index 94% rename from src/Parser/TokenParserInterface.php rename to src/Mapping/TokenParserInterface.php index 7011652..0ebcd39 100644 --- a/src/Parser/TokenParserInterface.php +++ b/src/Mapping/TokenParserInterface.php @@ -8,7 +8,7 @@ * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ -namespace Swoft\Auth\Parser; +namespace Swoft\Auth\Mapping; use Swoft\Auth\Bean\AuthSession; diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 245abe7..f1a4014 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -18,7 +18,9 @@ use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; +use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Bean\Annotation\Bean; +use Swoft\Bean\Annotation\Value; use Swoft\Http\Message\Middleware\MiddlewareInterface; /** @@ -28,6 +30,12 @@ */ class AclMiddleware implements MiddlewareInterface { + /** + * @Value("${config.auth.service}") + * @var string + */ + private $serviceClass = AuthUserService::class; + /** * Process an incoming server request and return a response, optionally delegating * response creation to a handler. @@ -39,14 +47,13 @@ class AclMiddleware implements MiddlewareInterface public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; - if (!App::hasBean(ServiceConstants::AUTH_USERS_SERVICE)) { - $error = sprintf('need AuthUserService %s', $requestHandler); + if (!App::hasBean($this->serviceClass)) { + $error = sprintf('can`t find %s', $this->serviceClass); throw new AuthException(ErrorCode::POST_DATA_INVALID, $error); } - /** @var AuthUserService $service */ - $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); - $flag = $service->auth($requestHandler,$request); - if (!$flag) { + /** @var AuthServiceInterface $service */ + $service = App::getBean($this->serviceClass); + if (!$service->auth($requestHandler,$request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); } $response = $handler->handle($request); diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php index ad492ef..f898b40 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/BearerTokenParser.php @@ -14,9 +14,12 @@ use Swoft\App; use Swoft\Auth\AuthManager; use Swoft\Auth\Constants\AuthConstants; -use Swoft\Auth\Constants\ServiceConstants; +use Swoft\Auth\Exception\AuthException; +use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthHandleInterface; +use Swoft\Auth\Mapping\AuthManagerInterface; use Swoft\Bean\Annotation\Bean; +use Swoft\Bean\Annotation\Value; /** * Class BearerTokenParser @@ -27,6 +30,12 @@ class BearerTokenParser implements AuthHandleInterface { const NAME = 'Bearer'; + /** + * @Value("${config.auth.manager}") + * @var string + */ + private $managerClass = AuthManager::class; + /** * @param \Psr\Http\Message\ServerRequestInterface $request * @return \Psr\Http\Message\ServerRequestInterface @@ -34,8 +43,12 @@ class BearerTokenParser implements AuthHandleInterface public function parse(ServerRequestInterface $request): ServerRequestInterface { $token = $this->getToken($request); - /** @var AuthManager $manager */ - $manager = App::getBean(ServiceConstants::AUTH_MANAGER); + if (!App::hasBean($this->managerClass)) { + $error = sprintf('can`t find %s', $this->managerClass); + throw new AuthException(ErrorCode::POST_DATA_INVALID, $error); + } + /** @var AuthManagerInterface $manager */ + $manager = App::getBean($this->managerClass); if ($token) { $res = $manager->authenticateToken($token); $request = $request->withAttribute(AuthConstants::IS_LOGIN, $res); diff --git a/src/Parser/JWTTokenParser.php b/src/Parser/JWTTokenParser.php index f6ae94e..f9212c0 100644 --- a/src/Parser/JWTTokenParser.php +++ b/src/Parser/JWTTokenParser.php @@ -12,6 +12,7 @@ use Firebase\JWT\JWT; use Swoft\Auth\Bean\AuthSession; +use Swoft\Auth\Mapping\TokenParserInterface; use Swoft\Bean\Annotation\Bean; use Swoft\Bean\Annotation\Value; From ad8b78596d0436b9b9916d2e3235b20ecfb33ef0 Mon Sep 17 00:00:00 2001 From: ott321 Date: Tue, 22 May 2018 22:03:29 +0800 Subject: [PATCH 12/24] fix Exception type --- src/AuthManager.php | 24 +++++++++++++++++++++--- src/Middleware/AclMiddleware.php | 5 ++--- src/Middleware/AuthMiddleware.php | 1 + src/Parser/BearerTokenParser.php | 6 ++---- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/AuthManager.php b/src/AuthManager.php index 10c6093..f600689 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -22,7 +22,9 @@ use Swoft\Auth\Mapping\AuthManagerInterface; use Swoft\Auth\Mapping\TokenParserInterface; use Swoft\Auth\Parser\JWTTokenParser; +use Swoft\Bean\Annotation\Value; use Swoft\Core\RequestContext; +use Swoft\Exception\RuntimeException; /** * Class AuthManager @@ -45,11 +47,19 @@ class AuthManager implements AuthManagerInterface */ protected $cacheEnable = false; + + protected $cacheClass; + /** * @var CacheInterface */ protected $cache; + /** + * @Value("${config.auth.tokenParser}") + * @var string + */ + protected $tokenParserClass = JWTTokenParser::class; /** * @var TokenParserInterface */ @@ -165,15 +175,23 @@ public function getAccountType($name) public function getTokenParser(): TokenParserInterface { - if (!$this->tokenParser instanceof TokenParserInterface) { - $this->tokenParser = App::getBean(JWTTokenParser::class); + if($this->tokenParser instanceof TokenParserInterface){ + return $this->tokenParser; + } + if(!App::hasBean($this->tokenParserClass)){ + throw new RuntimeException("can`t find %s",$this->tokenParserClass); + } + $tokenParser = App::getBean($this->tokenParserClass); + if(!$tokenParser instanceof TokenParserInterface){ + throw new RuntimeException("%s need implements TokenParserInterface ",$this->tokenParserClass); } + $this->tokenParser = $tokenParser; return $this->tokenParser; } public function getCacheClient(){ if(!$this->cache instanceof CacheInterface){ - throw new AuthException(ErrorCode::POST_DATA_INVALID,"AuthManager need cache client"); + throw new RuntimeException(" AuthManager need cache client"); } return $this->cache; } diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index f1a4014..58713eb 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -15,12 +15,12 @@ use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; use Swoft\Auth\AuthUserService; -use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Bean\Annotation\Bean; use Swoft\Bean\Annotation\Value; +use Swoft\Exception\RuntimeException; use Swoft\Http\Message\Middleware\MiddlewareInterface; /** @@ -48,8 +48,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface { $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; if (!App::hasBean($this->serviceClass)) { - $error = sprintf('can`t find %s', $this->serviceClass); - throw new AuthException(ErrorCode::POST_DATA_INVALID, $error); + throw new RuntimeException(sprintf('can`t find %s', $this->serviceClass)); } /** @var AuthServiceInterface $service */ $service = App::getBean($this->serviceClass); diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index 41ab33e..7b57917 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -42,4 +42,5 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $response = $handler->handle($request); return $response; } + } diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php index f898b40..0858419 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/BearerTokenParser.php @@ -14,12 +14,11 @@ use Swoft\App; use Swoft\Auth\AuthManager; use Swoft\Auth\Constants\AuthConstants; -use Swoft\Auth\Exception\AuthException; -use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthHandleInterface; use Swoft\Auth\Mapping\AuthManagerInterface; use Swoft\Bean\Annotation\Bean; use Swoft\Bean\Annotation\Value; +use Swoft\Exception\RuntimeException; /** * Class BearerTokenParser @@ -44,8 +43,7 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface { $token = $this->getToken($request); if (!App::hasBean($this->managerClass)) { - $error = sprintf('can`t find %s', $this->managerClass); - throw new AuthException(ErrorCode::POST_DATA_INVALID, $error); + throw new RuntimeException(sprintf('can`t find %s', $this->managerClass)); } /** @var AuthManagerInterface $manager */ $manager = App::getBean($this->managerClass); From 0ed261bb6d7af2e7412245b1a46b8b7d656f9e73 Mon Sep 17 00:00:00 2001 From: ott321 Date: Tue, 22 May 2018 23:07:30 +0800 Subject: [PATCH 13/24] fix core bug --- src/AuthUserService.php | 5 ++--- src/Bootstrap/CoreBean.php | 7 +++++++ src/Middleware/AclMiddleware.php | 11 ++--------- src/Parser/BearerTokenParser.php | 12 ++---------- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/AuthUserService.php b/src/AuthUserService.php index 0faf2d5..34bc52a 100644 --- a/src/AuthUserService.php +++ b/src/AuthUserService.php @@ -13,8 +13,6 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Constants\AuthConstants; -use Swoft\Auth\Exception\AuthException; -use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Core\RequestContext; @@ -65,7 +63,8 @@ public function getSession() */ public function auth(string $requestHandler, ServerRequestInterface $request): bool { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,"you need copy AuthUserService::auth method"); + echo sprintf(" 你访问了: %s",$requestHandler); + return true; } /** diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index 1792cf3..3b80044 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -11,6 +11,7 @@ namespace Swoft\Auth\Bootstrap; use Swoft\Auth\AuthManager; +use Swoft\Auth\AuthUserService; use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Parser\AuthorizationHeaderParser; use Swoft\Bean\Annotation\BootBean; @@ -32,6 +33,12 @@ public function beans() ServiceConstants::AUTH_REQUEST_HEADER_PARSER => [ 'class' => AuthorizationHeaderParser::class ], + ServiceConstants::AUTH_MANAGER=>[ + 'class' => AuthManager::class + ], + ServiceConstants::AUTH_USERS_SERVICE=>[ + 'class'=>AuthUserService::class + ] ]; } } diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 58713eb..155e1d9 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -15,6 +15,7 @@ use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; use Swoft\Auth\AuthUserService; +use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthServiceInterface; @@ -30,11 +31,6 @@ */ class AclMiddleware implements MiddlewareInterface { - /** - * @Value("${config.auth.service}") - * @var string - */ - private $serviceClass = AuthUserService::class; /** * Process an incoming server request and return a response, optionally delegating @@ -47,11 +43,8 @@ class AclMiddleware implements MiddlewareInterface public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; - if (!App::hasBean($this->serviceClass)) { - throw new RuntimeException(sprintf('can`t find %s', $this->serviceClass)); - } /** @var AuthServiceInterface $service */ - $service = App::getBean($this->serviceClass); + $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); if (!$service->auth($requestHandler,$request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); } diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php index 0858419..bfed3c3 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/BearerTokenParser.php @@ -14,6 +14,7 @@ use Swoft\App; use Swoft\Auth\AuthManager; use Swoft\Auth\Constants\AuthConstants; +use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Mapping\AuthHandleInterface; use Swoft\Auth\Mapping\AuthManagerInterface; use Swoft\Bean\Annotation\Bean; @@ -29,12 +30,6 @@ class BearerTokenParser implements AuthHandleInterface { const NAME = 'Bearer'; - /** - * @Value("${config.auth.manager}") - * @var string - */ - private $managerClass = AuthManager::class; - /** * @param \Psr\Http\Message\ServerRequestInterface $request * @return \Psr\Http\Message\ServerRequestInterface @@ -42,11 +37,8 @@ class BearerTokenParser implements AuthHandleInterface public function parse(ServerRequestInterface $request): ServerRequestInterface { $token = $this->getToken($request); - if (!App::hasBean($this->managerClass)) { - throw new RuntimeException(sprintf('can`t find %s', $this->managerClass)); - } /** @var AuthManagerInterface $manager */ - $manager = App::getBean($this->managerClass); + $manager = App::getBean(ServiceConstants::AUTH_MANAGER); if ($token) { $res = $manager->authenticateToken($token); $request = $request->withAttribute(AuthConstants::IS_LOGIN, $res); From 202ab77a385065cff84a0909a6785a9d26acbbce Mon Sep 17 00:00:00 2001 From: ott321 Date: Wed, 23 May 2018 00:25:19 +0800 Subject: [PATCH 14/24] fix cache bug & fix RuntimeException bug --- composer.json | 6 ++--- src/AuthManager.php | 42 +++++++++++++++++------------- src/Bootstrap/CoreBean.php | 4 ++- src/Middleware/AclMiddleware.php | 3 --- src/Parser/BearerTokenParser.php | 3 --- test/Cases/AuthManagerTest.php | 14 ++++++++++ test/Cases/AuthUserServiceTest.php | 1 + test/config/properties/app.php | 5 +++- 8 files changed, 49 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index 110899b..d42178f 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,7 @@ "require": { "swoft/http-server": "^1.0", "firebase/php-jwt": "^5.0", - "psr/simple-cache": "^1.0", - "friendsofphp/php-cs-fixer": "^2.11" + "psr/simple-cache": "^1.0" }, "autoload": { "psr-4": { @@ -32,7 +31,8 @@ ], "require-dev": { "eaglewu/swoole-ide-helper": "dev-master", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^5.7", + "friendsofphp/php-cs-fixer": "^2.11" }, "scripts": { "test": "./vendor/bin/phpunit -c phpunit.xml" diff --git a/src/AuthManager.php b/src/AuthManager.php index f600689..502db2c 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -22,7 +22,6 @@ use Swoft\Auth\Mapping\AuthManagerInterface; use Swoft\Auth\Mapping\TokenParserInterface; use Swoft\Auth\Parser\JWTTokenParser; -use Swoft\Bean\Annotation\Value; use Swoft\Core\RequestContext; use Swoft\Exception\RuntimeException; @@ -47,23 +46,24 @@ class AuthManager implements AuthManagerInterface */ protected $cacheEnable = false; - - protected $cacheClass; - /** * @var CacheInterface */ - protected $cache; + private $cache; + + /** + * @var string + */ + protected $cacheClass = ''; /** - * @Value("${config.auth.tokenParser}") * @var string */ protected $tokenParserClass = JWTTokenParser::class; /** * @var TokenParserInterface */ - protected $tokenParser; + private $tokenParser; public function getSessionDuration() { @@ -175,23 +175,29 @@ public function getAccountType($name) public function getTokenParser(): TokenParserInterface { - if($this->tokenParser instanceof TokenParserInterface){ - return $this->tokenParser; - } - if(!App::hasBean($this->tokenParserClass)){ - throw new RuntimeException("can`t find %s",$this->tokenParserClass); - } - $tokenParser = App::getBean($this->tokenParserClass); - if(!$tokenParser instanceof TokenParserInterface){ - throw new RuntimeException("%s need implements TokenParserInterface ",$this->tokenParserClass); + if(!$this->tokenParser instanceof TokenParserInterface){ + if(!App::hasBean($this->tokenParserClass)){ + throw new RuntimeException(sprintf("can`t find %s",$this->tokenParserClass)); + } + $tokenParser = App::getBean($this->tokenParserClass); + if(!$tokenParser instanceof TokenParserInterface){ + throw new RuntimeException(sprintf("%s need implements TokenParserInterface ",$this->tokenParserClass)); + } + $this->tokenParser = $tokenParser; } - $this->tokenParser = $tokenParser; return $this->tokenParser; } public function getCacheClient(){ if(!$this->cache instanceof CacheInterface){ - throw new RuntimeException(" AuthManager need cache client"); + if(!App::hasBean($this->cacheClass)){ + throw new RuntimeException(sprintf("can`t find %s",$this->cacheClass)); + } + $cache = App::getBean($this->cacheClass); + if(!$cache instanceof CacheInterface){ + throw new RuntimeException(sprintf("%s need implements CacheInterface ",$this->cacheClass)); + } + $this->cache = $cache; } return $this->cache; } diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index 3b80044..09ff4c7 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -14,6 +14,7 @@ use Swoft\Auth\AuthUserService; use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Parser\AuthorizationHeaderParser; +use Swoft\Auth\Parser\JWTTokenParser; use Swoft\Bean\Annotation\BootBean; use Swoft\Core\BootBeanInterface; @@ -34,7 +35,8 @@ public function beans() 'class' => AuthorizationHeaderParser::class ], ServiceConstants::AUTH_MANAGER=>[ - 'class' => AuthManager::class + 'class' => AuthManager::class, + 'tokenParserClass'=>JWTTokenParser::class, ], ServiceConstants::AUTH_USERS_SERVICE=>[ 'class'=>AuthUserService::class diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 155e1d9..469b73b 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -14,14 +14,11 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; -use Swoft\Auth\AuthUserService; use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Bean\Annotation\Bean; -use Swoft\Bean\Annotation\Value; -use Swoft\Exception\RuntimeException; use Swoft\Http\Message\Middleware\MiddlewareInterface; /** diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/BearerTokenParser.php index bfed3c3..92b2ed1 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/BearerTokenParser.php @@ -12,14 +12,11 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\App; -use Swoft\Auth\AuthManager; use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Mapping\AuthHandleInterface; use Swoft\Auth\Mapping\AuthManagerInterface; use Swoft\Bean\Annotation\Bean; -use Swoft\Bean\Annotation\Value; -use Swoft\Exception\RuntimeException; /** * Class BearerTokenParser diff --git a/test/Cases/AuthManagerTest.php b/test/Cases/AuthManagerTest.php index 2035f12..c27ab54 100644 --- a/test/Cases/AuthManagerTest.php +++ b/test/Cases/AuthManagerTest.php @@ -9,6 +9,7 @@ */ namespace SwoftTest\Auth; +use Swoft\Auth\AuthManager; /** * Class AuthManagerTest @@ -16,6 +17,19 @@ */ class AuthManagerTest extends AbstractTestCase { + /** + * @test + * @covers AuthManager::login() + */ + public function testLogin(){ + } + /** + * @test + * @covers AuthManager::authenticateToken() + */ + public function testAuthenticateToken(){ + + } } diff --git a/test/Cases/AuthUserServiceTest.php b/test/Cases/AuthUserServiceTest.php index 108b1f0..91cf70b 100644 --- a/test/Cases/AuthUserServiceTest.php +++ b/test/Cases/AuthUserServiceTest.php @@ -18,5 +18,6 @@ class AuthUserServiceTest extends AbstractTestCase */ public function testGetSession() { + } } diff --git a/test/config/properties/app.php b/test/config/properties/app.php index 7d21124..36869f9 100644 --- a/test/config/properties/app.php +++ b/test/config/properties/app.php @@ -18,7 +18,10 @@ ], 'env' => 'Base', 'auth' =>[ - 'cache'=>'' + 'jwt'=>[ + 'algorithm'=>'HS256', + 'secret'=>'1231231' + ] ], 'Service' => [ 'user' => [ From e48fd2f648c5e300bd08f5e538b3659b7913f871 Mon Sep 17 00:00:00 2001 From: ott321 Date: Wed, 23 May 2018 00:49:55 +0800 Subject: [PATCH 15/24] add some test class --- .gitignore | 2 +- .php_cs | 1 + .travis.yml | 1 + phpunit.xml | 1 + test/Cases/Helper/ErrorCodeHelperTest.php | 12 ++++++++++++ test/Cases/Middleware/AclMiddlewareTest.php | 1 + test/Cases/Parser/BasicAuthParserTest.php | 2 ++ test/Cases/Parser/BearerTokenParserTest.php | 20 ++++++++++++++++++++ test/Cases/Parser/JWTTokenParserTest.php | 18 ++++++++++++++++++ test/config/beans/base.php | 8 +++++++- 10 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 test/Cases/Parser/BearerTokenParserTest.php create mode 100644 test/Cases/Parser/JWTTokenParserTest.php diff --git a/.gitignore b/.gitignore index 6156e88..cf3f6de 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ vendor/ temp/ *.lock .phpintel/ -.DS_Store \ No newline at end of file +.DS_Store diff --git a/.php_cs b/.php_cs index 41e1b73..7821b07 100644 --- a/.php_cs +++ b/.php_cs @@ -36,3 +36,4 @@ return PhpCsFixer\Config::create() ->in(__DIR__) ) ->setUsingCache(false); + diff --git a/.travis.yml b/.travis.yml index e12681e..93def9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,3 +18,4 @@ before_script: - composer update script: composer test + diff --git a/phpunit.xml b/phpunit.xml index b259449..37e68d6 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -19,3 +19,4 @@ + diff --git a/test/Cases/Helper/ErrorCodeHelperTest.php b/test/Cases/Helper/ErrorCodeHelperTest.php index 44c1e5e..0c9403d 100644 --- a/test/Cases/Helper/ErrorCodeHelperTest.php +++ b/test/Cases/Helper/ErrorCodeHelperTest.php @@ -10,8 +10,20 @@ namespace SwoftTest\Auth\Helper; +use Swoft\App; +use Swoft\Auth\Helper\ErrorCode; +use Swoft\Auth\Helper\ErrorCodeHelper; use SwoftTest\Auth\AbstractTestCase; class ErrorCodeHelperTest extends AbstractTestCase { + /** + * @test + * @covers ErrorCodeHelper::get() + */ + public function testGet(){ + $helper = new ErrorCodeHelper(); + $arr = $helper->get(ErrorCode::ACCESS_DENIED); + $this->assertArrayHasKey('statusCode',$arr); + } } diff --git a/test/Cases/Middleware/AclMiddlewareTest.php b/test/Cases/Middleware/AclMiddlewareTest.php index 20a5f12..85ef061 100644 --- a/test/Cases/Middleware/AclMiddlewareTest.php +++ b/test/Cases/Middleware/AclMiddlewareTest.php @@ -14,4 +14,5 @@ class AclMiddlewareTest extends AbstractTestCase { + } diff --git a/test/Cases/Parser/BasicAuthParserTest.php b/test/Cases/Parser/BasicAuthParserTest.php index 16aab2d..7dcc689 100644 --- a/test/Cases/Parser/BasicAuthParserTest.php +++ b/test/Cases/Parser/BasicAuthParserTest.php @@ -14,4 +14,6 @@ class BasicAuthParserTest extends AbstractTestCase { + + } diff --git a/test/Cases/Parser/BearerTokenParserTest.php b/test/Cases/Parser/BearerTokenParserTest.php new file mode 100644 index 0000000..bb2f361 --- /dev/null +++ b/test/Cases/Parser/BearerTokenParserTest.php @@ -0,0 +1,20 @@ + + */ + +namespace SwoftTest\Auth\Parser; + +use SwoftTest\Auth\AbstractTestCase; + +class BearerTokenParserTest extends AbstractTestCase +{ + + public function testParse(){ + + } +} \ No newline at end of file diff --git a/test/Cases/Parser/JWTTokenParserTest.php b/test/Cases/Parser/JWTTokenParserTest.php new file mode 100644 index 0000000..4bd9f78 --- /dev/null +++ b/test/Cases/Parser/JWTTokenParserTest.php @@ -0,0 +1,18 @@ + + */ + +namespace SwoftTest\Auth\Parser; + + +use SwoftTest\Auth\AbstractTestCase; + +class JWTTokenParserTest extends AbstractTestCase +{ + +} \ No newline at end of file diff --git a/test/config/beans/base.php b/test/config/beans/base.php index 6a1ce8d..b25b946 100644 --- a/test/config/beans/base.php +++ b/test/config/beans/base.php @@ -7,4 +7,10 @@ * @contact group@swoft.org * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ -return []; +return [ + 'serverDispatcher' => [ + 'middlewares' => [ + \Swoft\Auth\Middleware\AuthMiddleware::class, + ] + ], +]; From 7386e2faf6d2ba36232bd8433d99b300a388d766 Mon Sep 17 00:00:00 2001 From: ott321 Date: Thu, 24 May 2018 10:09:34 +0800 Subject: [PATCH 16/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B5=8B=E8=AF=95...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AuthUserService.php | 5 ++-- src/Bean/AuthSession.php | 2 +- test/Cases/Parser/BasicAuthParserTest.php | 4 ++++ test/Cases/Parser/JWTTokenParserTest.php | 28 +++++++++++++++++++++++ test/bootstrap.php | 9 ++------ test/config/properties/app.php | 4 +++- 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/AuthUserService.php b/src/AuthUserService.php index 34bc52a..bb0e0a7 100644 --- a/src/AuthUserService.php +++ b/src/AuthUserService.php @@ -13,6 +13,8 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Constants\AuthConstants; +use Swoft\Auth\Exception\AuthException; +use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Core\RequestContext; @@ -63,8 +65,7 @@ public function getSession() */ public function auth(string $requestHandler, ServerRequestInterface $request): bool { - echo sprintf(" 你访问了: %s",$requestHandler); - return true; + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,"you need copy AuthUserService::auth method"); } /** diff --git a/src/Bean/AuthSession.php b/src/Bean/AuthSession.php index ed0306c..10bd75e 100644 --- a/src/Bean/AuthSession.php +++ b/src/Bean/AuthSession.php @@ -48,7 +48,7 @@ class AuthSession /** * @var array Expand data, define it yourself */ - protected $extendedData=null; + protected $extendedData=[]; /** * @return string diff --git a/test/Cases/Parser/BasicAuthParserTest.php b/test/Cases/Parser/BasicAuthParserTest.php index 7dcc689..16f917a 100644 --- a/test/Cases/Parser/BasicAuthParserTest.php +++ b/test/Cases/Parser/BasicAuthParserTest.php @@ -15,5 +15,9 @@ class BasicAuthParserTest extends AbstractTestCase { + public function testParser(){ + $request = $this->raw("get","test",[],['Authorization'=>'Basic 1'],"test"); + var_dump($request); + } } diff --git a/test/Cases/Parser/JWTTokenParserTest.php b/test/Cases/Parser/JWTTokenParserTest.php index 4bd9f78..716e5a7 100644 --- a/test/Cases/Parser/JWTTokenParserTest.php +++ b/test/Cases/Parser/JWTTokenParserTest.php @@ -10,9 +10,37 @@ namespace SwoftTest\Auth\Parser; +use Swoft\App; +use Swoft\Auth\Bean\AuthSession; +use Swoft\Auth\Parser\JWTTokenParser; use SwoftTest\Auth\AbstractTestCase; class JWTTokenParserTest extends AbstractTestCase { + /** + * @test + * @covers JWTTokenParser::getToken() + * @return string + */ + public function testGetToken(){ + $parser = App::getBean(JWTTokenParser::class); + $session = new AuthSession(); + $session->setIdentity(1); + $session->setExpirationTime(time()+10); + $token = $parser->getToken($session); + $this->assertStringStartsWith("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9",$token); + return $token; + } + + /** + * @test + * @covers JWTTokenParser::getSession() + */ + public function testGetSession(){ + $token = $this->testGetToken(); + $parser = App::getBean(JWTTokenParser::class); + $session = $parser->getSession($token); + $this->assertEquals(1,$session->getIdentity()); + } } \ No newline at end of file diff --git a/test/bootstrap.php b/test/bootstrap.php index e001879..b7aae49 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -7,13 +7,8 @@ * @contact group@swoft.org * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ -if (file_exists($file = dirname(__DIR__, 3) . '/autoload.php')) { - require $file; -} elseif (file_exists($file = dirname(__DIR__) . '/vendor/autoload.php')) { - require $file; -} else { - exit('OO, The composer autoload file is not found!'); -} + +require_once dirname(__DIR__) . '/vendor/autoload.php'; require_once __DIR__ . '/config/define.php'; diff --git a/test/config/properties/app.php b/test/config/properties/app.php index 36869f9..77c2d09 100644 --- a/test/config/properties/app.php +++ b/test/config/properties/app.php @@ -7,11 +7,13 @@ * @contact group@swoft.org * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ + + return [ 'version' => '1.0', 'autoInitBean' => true, 'beanScan' => [ - 'Swoft\\Http\\Server\\Test\\Testing' => BASE_PATH.'/Testing' + "Swoft\\Auth"=>'@root/../src' ], 'I18n' => [ 'sourceLanguage' => '@root/resources/messages/', From 87215c9f564158357b7b1ae189ca147359ca50a6 Mon Sep 17 00:00:00 2001 From: ott321 Date: Sat, 2 Jun 2018 00:19:12 +0800 Subject: [PATCH 17/24] finished unittest --- composer.json | 3 +- src/AuthAccount.php | 47 +++++++++++++ src/AuthManager.php | 28 ++++---- src/AuthUserService.php | 3 +- src/Constants/ServiceConstants.php | 2 +- src/Mapping/AuthManagerInterface.php | 16 ++--- src/Mapping/AuthServiceInterface.php | 16 ++--- src/Middleware/AclMiddleware.php | 4 +- src/Middleware/AuthMiddleware.php | 1 - test/Cases/AbstractTestCase.php | 77 ++++++++++++--------- test/Cases/AuthManagerTest.php | 35 ---------- test/Cases/AuthUserServiceTest.php | 23 ------ test/Cases/Helper/ErrorCodeHelperTest.php | 6 +- test/Cases/Middleware/AclMiddlewareTest.php | 18 ----- test/Cases/Parser/BasicAuthParserTest.php | 35 ++++++++-- test/Cases/Parser/BearerTokenParserTest.php | 45 +++++++++--- test/Cases/Parser/JWTTokenParserTest.php | 28 ++++---- test/config/beans/base.php | 2 +- test/config/properties/app.php | 27 ++++---- 19 files changed, 228 insertions(+), 188 deletions(-) create mode 100644 src/AuthAccount.php delete mode 100644 test/Cases/AuthManagerTest.php delete mode 100644 test/Cases/AuthUserServiceTest.php delete mode 100644 test/Cases/Middleware/AclMiddlewareTest.php diff --git a/composer.json b/composer.json index d42178f..c24d5fa 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,8 @@ "require": { "swoft/http-server": "^1.0", "firebase/php-jwt": "^5.0", - "psr/simple-cache": "^1.0" + "psr/simple-cache": "^1.0", + "swoft/framework": "^1.0" }, "autoload": { "psr-4": { diff --git a/src/AuthAccount.php b/src/AuthAccount.php new file mode 100644 index 0000000..572c5d6 --- /dev/null +++ b/src/AuthAccount.php @@ -0,0 +1,47 @@ +setIdentity(1); + $result->setExtendedData([]); + return $result; + } + + /** + * @param string $identity Identity + * + * @return bool Authentication successful + */ + public function authenticate(string $identity): bool + { + return true; + } +} diff --git a/src/AuthManager.php b/src/AuthManager.php index 502db2c..f027afb 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -60,6 +60,7 @@ class AuthManager implements AuthManagerInterface * @var string */ protected $tokenParserClass = JWTTokenParser::class; + /** * @var TokenParserInterface */ @@ -122,7 +123,7 @@ public function login(string $accountTypeName, array $data):AuthSession $session->getExpirationTime() ); } catch (InvalidArgumentException $e) { - $err = sprintf('%s 参数无效,message : %s', $session->getIdentity(),$e->getMessage()); + $err = sprintf('%s 参数无效,message : %s', $session->getIdentity(), $e->getMessage()); throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, $err); } } @@ -175,27 +176,28 @@ public function getAccountType($name) public function getTokenParser(): TokenParserInterface { - if(!$this->tokenParser instanceof TokenParserInterface){ - if(!App::hasBean($this->tokenParserClass)){ - throw new RuntimeException(sprintf("can`t find %s",$this->tokenParserClass)); + if (!$this->tokenParser instanceof TokenParserInterface) { + if (!App::hasBean($this->tokenParserClass)) { + throw new RuntimeException(sprintf('can`t find %s', $this->tokenParserClass)); } $tokenParser = App::getBean($this->tokenParserClass); - if(!$tokenParser instanceof TokenParserInterface){ - throw new RuntimeException(sprintf("%s need implements TokenParserInterface ",$this->tokenParserClass)); + if (!$tokenParser instanceof TokenParserInterface) { + throw new RuntimeException(sprintf('%s need implements TokenParserInterface ', $this->tokenParserClass)); } $this->tokenParser = $tokenParser; } return $this->tokenParser; } - public function getCacheClient(){ - if(!$this->cache instanceof CacheInterface){ - if(!App::hasBean($this->cacheClass)){ - throw new RuntimeException(sprintf("can`t find %s",$this->cacheClass)); + public function getCacheClient() + { + if (!$this->cache instanceof CacheInterface) { + if (!App::hasBean($this->cacheClass)) { + throw new RuntimeException(sprintf('can`t find %s', $this->cacheClass)); } $cache = App::getBean($this->cacheClass); - if(!$cache instanceof CacheInterface){ - throw new RuntimeException(sprintf("%s need implements CacheInterface ",$this->cacheClass)); + if (!$cache instanceof CacheInterface) { + throw new RuntimeException(sprintf('%s need implements CacheInterface ', $this->cacheClass)); } $this->cache = $cache; } @@ -239,7 +241,7 @@ public function authenticateToken(string $token):bool throw new AuthException(ErrorCode::AUTH_TOKEN_INVALID); } } catch (InvalidArgumentException $e) { - $err = sprintf('%s 参数无效,message : %s', $session->getIdentity(),$e->getMessage()); + $err = sprintf('%s 参数无效,message : %s', $session->getIdentity(), $e->getMessage()); throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, $err); } } diff --git a/src/AuthUserService.php b/src/AuthUserService.php index bb0e0a7..a538caa 100644 --- a/src/AuthUserService.php +++ b/src/AuthUserService.php @@ -65,7 +65,7 @@ public function getSession() */ public function auth(string $requestHandler, ServerRequestInterface $request): bool { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED,"you need copy AuthUserService::auth method"); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('AuthUserService::auth() method should be implemented in %s', static::class)); } /** @@ -80,5 +80,4 @@ protected function getHandlerArray(string $handler) } return $segments; } - } diff --git a/src/Constants/ServiceConstants.php b/src/Constants/ServiceConstants.php index 30c42f9..2d85f8c 100644 --- a/src/Constants/ServiceConstants.php +++ b/src/Constants/ServiceConstants.php @@ -12,7 +12,7 @@ class ServiceConstants { - const AUTH_REQUEST_HEADER_PARSER = 'AuthRequestHeaderParser'; + const AUTH_REQUEST_HEADER_PARSER = 'AuthorizationRequestHeaderParser'; const AUTH_MANAGER = 'AuthManager'; diff --git a/src/Mapping/AuthManagerInterface.php b/src/Mapping/AuthManagerInterface.php index 1d840bb..be9c941 100644 --- a/src/Mapping/AuthManagerInterface.php +++ b/src/Mapping/AuthManagerInterface.php @@ -1,20 +1,19 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Mapping; - use Swoft\Auth\Bean\AuthSession; interface AuthManagerInterface { - /** * @param $accountTypeName * @param array $data @@ -27,5 +26,4 @@ public function login(string $accountTypeName, array $data):AuthSession; * @return bool */ public function authenticateToken(string $token):bool ; - -} \ No newline at end of file +} diff --git a/src/Mapping/AuthServiceInterface.php b/src/Mapping/AuthServiceInterface.php index 7d2dcdd..7ef4ad3 100644 --- a/src/Mapping/AuthServiceInterface.php +++ b/src/Mapping/AuthServiceInterface.php @@ -1,20 +1,19 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace Swoft\Auth\Mapping; - use Psr\Http\Message\ServerRequestInterface; interface AuthServiceInterface { - /** * * $controller = $this->getHandlerArray($requestHandler)[0]; @@ -31,5 +30,4 @@ interface AuthServiceInterface * @return bool */ public function auth(string $requestHandler, ServerRequestInterface $request): bool; - -} \ No newline at end of file +} diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 469b73b..657c0b7 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -28,7 +28,6 @@ */ class AclMiddleware implements MiddlewareInterface { - /** * Process an incoming server request and return a response, optionally delegating * response creation to a handler. @@ -42,11 +41,10 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; /** @var AuthServiceInterface $service */ $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); - if (!$service->auth($requestHandler,$request)) { + if (!$service->auth($requestHandler, $request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); } $response = $handler->handle($request); return $response; } - } diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index 7b57917..41ab33e 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -42,5 +42,4 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $response = $handler->handle($request); return $response; } - } diff --git a/test/Cases/AbstractTestCase.php b/test/Cases/AbstractTestCase.php index ab16bd0..52fda46 100644 --- a/test/Cases/AbstractTestCase.php +++ b/test/Cases/AbstractTestCase.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Swoft\App; use Swoft\Helper\ArrayHelper; +use Swoft\Http\Server\Router\HandlerMapping; use Swoft\Testing\SwooleRequest as TestSwooleRequest; use Swoft\Testing\SwooleResponse as TestSwooleResponse; use Swoft\Http\Message\Testing\Web\Request; @@ -30,14 +31,24 @@ class AbstractTestCase extends TestCase const ACCEPT_RAW = 'text/plain'; + protected function registerRoute() + { + /** @var HandlerMapping $router */ + $router = App::getBean('httpRouter'); + + $router->get('/', function () { + return [1]; + }); + } + /** * Send a mock request * * @param string $method * @param string $uri - * @param array $parameters + * @param array $parameters * @param string $accept - * @param array $headers + * @param array $headers * @param string $rawContent * @return bool|\Swoft\Http\Message\Testing\Web\Response */ @@ -52,7 +63,7 @@ public function request( $method = strtoupper($method); $swooleResponse = new TestSwooleResponse(); $swooleRequest = new TestSwooleRequest(); - + $this->registerRoute(); $this->buildMockRequest($method, $uri, $parameters, $accept, $swooleRequest, $headers); $swooleRequest->setRawContent($rawContent); @@ -70,8 +81,8 @@ public function request( * * @param string $method * @param string $uri - * @param array $parameters - * @param array $headers + * @param array $parameters + * @param array $headers * @param string $rawContent * @return bool|\Swoft\Http\Message\Testing\Web\Response */ @@ -90,8 +101,8 @@ public function json( * * @param string $method * @param string $uri - * @param array $parameters - * @param array $headers + * @param array $parameters + * @param array $headers * @param string $rawContent * @return bool|\Swoft\Http\Message\Testing\Web\Response */ @@ -110,8 +121,8 @@ public function view( * * @param string $method * @param string $uri - * @param array $parameters - * @param array $headers + * @param array $parameters + * @param array $headers * @param string $rawContent * @return bool|\Swoft\Http\Message\Testing\Web\Response */ @@ -126,12 +137,12 @@ public function raw( } /** - * @param string $method - * @param string $uri - * @param array $parameters - * @param string $accept + * @param string $method + * @param string $uri + * @param array $parameters + * @param string $accept * @param \Swoole\Http\Request $swooleRequest - * @param array $headers + * @param array $headers */ protected function buildMockRequest( string $method, @@ -147,31 +158,31 @@ protected function buildMockRequest( parse_str($urlAry['query'], $urlParams); } $defaultHeaders = [ - 'host' => '127.0.0.1', - 'connection' => 'keep-alive', - 'cache-control' => 'max-age=0', - 'user-agent' => 'PHPUnit', + 'host' => '127.0.0.1', + 'connection' => 'keep-alive', + 'cache-control' => 'max-age=0', + 'user-agent' => 'PHPUnit', 'upgrade-insecure-requests' => '1', - 'accept' => $accept, - 'dnt' => '1', - 'accept-encoding' => 'gzip, deflate, br', - 'accept-language' => 'zh-CN,zh;q=0.8,en;q=0.6,it-IT;q=0.4,it;q=0.2', + 'accept' => $accept, + 'dnt' => '1', + 'accept-encoding' => 'gzip, deflate, br', + 'accept-language' => 'zh-CN,zh;q=0.8,en;q=0.6,it-IT;q=0.4,it;q=0.2', ]; $swooleRequest->fd = 1; $swooleRequest->header = ArrayHelper::merge($headers, $defaultHeaders); $swooleRequest->server = [ - 'request_method' => $method, - 'request_uri' => $uri, - 'path_info' => '/', - 'request_time' => microtime(), + 'request_method' => $method, + 'request_uri' => $uri, + 'path_info' => '/', + 'request_time' => microtime(), 'request_time_float' => microtime(true), - 'server_port' => 80, - 'remote_port' => 54235, - 'remote_addr' => '10.0.2.2', - 'master_time' => microtime(), - 'server_protocol' => 'HTTP/1.1', - 'server_software' => 'swoole-http-server', + 'server_port' => 80, + 'remote_port' => 54235, + 'remote_addr' => '10.0.2.2', + 'master_time' => microtime(), + 'server_protocol' => 'HTTP/1.1', + 'server_software' => 'swoole-http-server', ]; if ($method == 'GET') { @@ -180,7 +191,7 @@ protected function buildMockRequest( $swooleRequest->post = $parameters; } - if (! empty($urlParams)) { + if (!empty($urlParams)) { $get = empty($swooleRequest->get) ? [] : $swooleRequest->get; $swooleRequest->get = array_merge($urlParams, $get); } diff --git a/test/Cases/AuthManagerTest.php b/test/Cases/AuthManagerTest.php deleted file mode 100644 index c27ab54..0000000 --- a/test/Cases/AuthManagerTest.php +++ /dev/null @@ -1,35 +0,0 @@ -get(ErrorCode::ACCESS_DENIED); - $this->assertArrayHasKey('statusCode',$arr); + $this->assertArrayHasKey('statusCode', $arr); } } diff --git a/test/Cases/Middleware/AclMiddlewareTest.php b/test/Cases/Middleware/AclMiddlewareTest.php deleted file mode 100644 index 85ef061..0000000 --- a/test/Cases/Middleware/AclMiddlewareTest.php +++ /dev/null @@ -1,18 +0,0 @@ -raw("get","test",[],['Authorization'=>'Basic 1'],"test"); - var_dump($request); + protected function registerRoute() + { + /** @var HandlerMapping $router */ + $router = App::getBean('httpRouter'); + $router->get('/', function (Request $request) { + $name = $request->getAttribute(AuthConstants::BASIC_USER_NAME); + $pd = $request->getAttribute(AuthConstants::BASIC_PASSWORD); + return ['username' => $name, 'password' => $pd]; + }); } + /** + * @test + * @covers BasicAuthParser::parse() + */ + public function testParser() + { + $username = 'user'; + $password = '123'; + $parser = base64_encode($username . ':' . $password); + $response = $this->request('GET', '/', [], self::ACCEPT_JSON, ['Authorization' => 'Basic ' . $parser], 'test'); + $res = $response->getBody()->getContents(); + $this->assertEquals(json_decode($res, true), ['username' => $username, 'password' => $password]); + } } diff --git a/test/Cases/Parser/BearerTokenParserTest.php b/test/Cases/Parser/BearerTokenParserTest.php index bb2f361..6cffc02 100644 --- a/test/Cases/Parser/BearerTokenParserTest.php +++ b/test/Cases/Parser/BearerTokenParserTest.php @@ -1,20 +1,49 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace SwoftTest\Auth\Parser; +use Swoft\App; +use Swoft\Auth\AuthUserService; +use Swoft\Auth\Constants\ServiceConstants; +use Swoft\Auth\Parser\BearerTokenParser; +use Swoft\Http\Message\Server\Request; +use Swoft\Http\Server\Router\HandlerMapping; use SwoftTest\Auth\AbstractTestCase; class BearerTokenParserTest extends AbstractTestCase { + protected function registerRoute() + { + /** @var HandlerMapping $router */ + $router = App::getBean('httpRouter'); + $router->get('/test', function (Request $request) { + /** @var AuthUserService $service */ + $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); + $session = $service->getSession(); + return ['id'=>$session->getIdentity()]; + }); + } - public function testParse(){ - + /** + * @test + * @covers AuthManager::authenticateToken() + * @covers BearerTokenParser::parse() + * @covers AuthAccount::authenticate() + */ + public function testParse() + { + $jwt = new JWTTokenParserTest(); + $token = $jwt->testGetToken(); + $response = $this->request('GET', '/test', [], self::ACCEPT_JSON, ['Authorization' => 'Bearer ' . $token], 'test'); + $res = $response->getBody()->getContents(); + $this->assertEquals(json_decode($res, true), ['id' => 1]); } -} \ No newline at end of file +} diff --git a/test/Cases/Parser/JWTTokenParserTest.php b/test/Cases/Parser/JWTTokenParserTest.php index 716e5a7..3c57828 100644 --- a/test/Cases/Parser/JWTTokenParserTest.php +++ b/test/Cases/Parser/JWTTokenParserTest.php @@ -1,16 +1,17 @@ + * This file is part of Swoft. + * + * @link https://swoft.org + * @document https://doc.swoft.org + * @contact group@swoft.org + * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace SwoftTest\Auth\Parser; - use Swoft\App; +use Swoft\Auth\AuthAccount; use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Parser\JWTTokenParser; use SwoftTest\Auth\AbstractTestCase; @@ -22,13 +23,15 @@ class JWTTokenParserTest extends AbstractTestCase * @covers JWTTokenParser::getToken() * @return string */ - public function testGetToken(){ + public function testGetToken() + { $parser = App::getBean(JWTTokenParser::class); $session = new AuthSession(); $session->setIdentity(1); $session->setExpirationTime(time()+10); + $session->setAccountTypeName(AuthAccount::class); $token = $parser->getToken($session); - $this->assertStringStartsWith("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9",$token); + $this->assertStringStartsWith('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9', $token); return $token; } @@ -36,11 +39,12 @@ public function testGetToken(){ * @test * @covers JWTTokenParser::getSession() */ - public function testGetSession(){ + public function testGetSession() + { $token = $this->testGetToken(); $parser = App::getBean(JWTTokenParser::class); + /** @var AuthSession $session */ $session = $parser->getSession($token); - $this->assertEquals(1,$session->getIdentity()); + $this->assertEquals(1, $session->getIdentity()); } - -} \ No newline at end of file +} diff --git a/test/config/beans/base.php b/test/config/beans/base.php index b25b946..25772e0 100644 --- a/test/config/beans/base.php +++ b/test/config/beans/base.php @@ -10,7 +10,7 @@ return [ 'serverDispatcher' => [ 'middlewares' => [ - \Swoft\Auth\Middleware\AuthMiddleware::class, + Swoft\Auth\Middleware\AuthMiddleware::class, ] ], ]; diff --git a/test/config/properties/app.php b/test/config/properties/app.php index 77c2d09..151a8af 100644 --- a/test/config/properties/app.php +++ b/test/config/properties/app.php @@ -8,24 +8,27 @@ * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ - return [ - 'version' => '1.0', - 'autoInitBean' => true, - 'beanScan' => [ - "Swoft\\Auth"=>'@root/../src' + 'version' => '1.0', + 'autoInitBean' => true, + 'bootScan' => [ + 'Swoft\\Auth' => BASE_PATH . '/../src', + ], + 'beanScan' => [ + 'Swoft\\Auth' => BASE_PATH . '/../src', + 'SwoftTest\\Auth\\'=> BASE_PATH .'/Cases/Base' ], - 'I18n' => [ + 'I18n' => [ 'sourceLanguage' => '@root/resources/messages/', ], - 'env' => 'Base', - 'auth' =>[ - 'jwt'=>[ - 'algorithm'=>'HS256', - 'secret'=>'1231231' + 'env' => 'Base', + 'auth' => [ + 'jwt' => [ + 'algorithm' => 'HS256', + 'secret' => '1231231' ] ], - 'Service' => [ + 'Service' => [ 'user' => [ 'timeout' => 3000 ] From 131621ec3f1e0fc3f8876369c42b4396447ce061 Mon Sep 17 00:00:00 2001 From: ott321 Date: Sat, 2 Jun 2018 00:23:51 +0800 Subject: [PATCH 18/24] finished unittest --- test/Cases/Parser/BearerTokenParserTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Cases/Parser/BearerTokenParserTest.php b/test/Cases/Parser/BearerTokenParserTest.php index 6cffc02..d550a71 100644 --- a/test/Cases/Parser/BearerTokenParserTest.php +++ b/test/Cases/Parser/BearerTokenParserTest.php @@ -37,6 +37,7 @@ protected function registerRoute() * @covers AuthManager::authenticateToken() * @covers BearerTokenParser::parse() * @covers AuthAccount::authenticate() + * @covers AuthUserService::getSession() */ public function testParse() { From d742030f321f010aba9a0b912405cefd106ede90 Mon Sep 17 00:00:00 2001 From: ott321 Date: Tue, 5 Jun 2018 10:31:41 +0800 Subject: [PATCH 19/24] fix stytel --- src/AuthManager.php | 13 ++++++++++-- src/Exception/AuthException.php | 4 ++++ src/Helper/ErrorCode.php | 6 +----- src/Mapping/AccountTypeInterface.php | 4 ++-- ...Interface.php => AuthHandlerInterface.php} | 4 ++-- src/Mapping/AuthorizationParserInterface.php | 6 +++++- src/Middleware/AclMiddleware.php | 4 +++- src/Middleware/AuthMiddleware.php | 8 ++++++-- src/Parser/AuthorizationHeaderParser.php | 20 ++++++++++++------- .../BasicAuthHandler.php} | 8 ++++---- .../BearerTokenHandler.php} | 8 ++++---- .../Cases/Account/TestAccount.php | 9 ++++----- .../BasicAuthParserTest.php | 5 ++--- .../BearerTokenParserTest.php | 6 ++---- test/Cases/Parser/JWTTokenParserTest.php | 4 ++-- test/config/properties/app.php | 2 +- 16 files changed, 66 insertions(+), 45 deletions(-) rename src/Mapping/{AuthHandleInterface.php => AuthHandlerInterface.php} (78%) rename src/Parser/{BasicAuthParser.php => Handler/BasicAuthHandler.php} (87%) rename src/Parser/{BearerTokenParser.php => Handler/BearerTokenHandler.php} (87%) rename src/AuthAccount.php => test/Cases/Account/TestAccount.php (82%) rename test/Cases/{Parser => Handler}/BasicAuthParserTest.php (92%) rename test/Cases/{Parser => Handler}/BearerTokenParserTest.php (89%) diff --git a/src/AuthManager.php b/src/AuthManager.php index f027afb..881cf76 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -84,6 +84,9 @@ public function getSession() return RequestContext::getContextDataByKey(AuthConstants::AUTH_SESSION); } + /** + * @param AuthSession $session + */ public function setSession(AuthSession $session) { RequestContext::setContextData([AuthConstants::AUTH_SESSION => $session]); @@ -94,7 +97,7 @@ public function setSession(AuthSession $session) * * Check if a user is currently logged in */ - public function loggedIn() + public function isLoggedIn() { return $this->getSession() instanceof AuthSession; } @@ -123,7 +126,7 @@ public function login(string $accountTypeName, array $data):AuthSession $session->getExpirationTime() ); } catch (InvalidArgumentException $e) { - $err = sprintf('%s 参数无效,message : %s', $session->getIdentity(), $e->getMessage()); + $err = sprintf('%s Invalid Argument : %s', $session->getIdentity(), $e->getMessage()); throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, $err); } } @@ -174,6 +177,9 @@ public function getAccountType($name) return $account; } + /** + * @return TokenParserInterface + */ public function getTokenParser(): TokenParserInterface { if (!$this->tokenParser instanceof TokenParserInterface) { @@ -189,6 +195,9 @@ public function getTokenParser(): TokenParserInterface return $this->tokenParser; } + /** + * @return CacheInterface + */ public function getCacheClient() { if (!$this->cache instanceof CacheInterface) { diff --git a/src/Exception/AuthException.php b/src/Exception/AuthException.php index 0f8b705..051fc8b 100644 --- a/src/Exception/AuthException.php +++ b/src/Exception/AuthException.php @@ -13,6 +13,10 @@ use Swoft\Exception\RuntimeException; use Throwable; +/** + * Class AuthException + * @package Swoft\Auth\Exception + */ class AuthException extends RuntimeException { public function __construct(int $code = 0, string $message = '', Throwable $previous = null) diff --git a/src/Helper/ErrorCode.php b/src/Helper/ErrorCode.php index 8fc9961..f91d2df 100644 --- a/src/Helper/ErrorCode.php +++ b/src/Helper/ErrorCode.php @@ -11,12 +11,8 @@ namespace Swoft\Auth\Helper; /** - * User: sl - * Date: 2018/5/20 - * Time: 下午5:41 - * Interface ErrorCodeInterface + * Class ErrorCode * @package Swoft\Auth\Helper - * @author April2 */ class ErrorCode { diff --git a/src/Mapping/AccountTypeInterface.php b/src/Mapping/AccountTypeInterface.php index 099a744..57d0918 100644 --- a/src/Mapping/AccountTypeInterface.php +++ b/src/Mapping/AccountTypeInterface.php @@ -14,9 +14,9 @@ interface AccountTypeInterface { - const LOGIN_DATA_USERNAME = 'username'; + const LOGIN_IDENTITY = 'identity'; - const LOGIN_DATA_PASSWORD = 'password'; + const LOGIN_CREDENTIAL = 'credential'; /** * @param array $data Login data diff --git a/src/Mapping/AuthHandleInterface.php b/src/Mapping/AuthHandlerInterface.php similarity index 78% rename from src/Mapping/AuthHandleInterface.php rename to src/Mapping/AuthHandlerInterface.php index d7ace88..f87e97f 100644 --- a/src/Mapping/AuthHandleInterface.php +++ b/src/Mapping/AuthHandlerInterface.php @@ -12,11 +12,11 @@ use Psr\Http\Message\ServerRequestInterface; -interface AuthHandleInterface +interface AuthHandlerInterface { /** * @param \Psr\Http\Message\ServerRequestInterface $request * @return \Psr\Http\Message\ServerRequestInterface */ - public function parse(ServerRequestInterface $request): ServerRequestInterface; + public function handle(ServerRequestInterface $request): ServerRequestInterface; } diff --git a/src/Mapping/AuthorizationParserInterface.php b/src/Mapping/AuthorizationParserInterface.php index f40e6b7..b96c8ac 100644 --- a/src/Mapping/AuthorizationParserInterface.php +++ b/src/Mapping/AuthorizationParserInterface.php @@ -14,5 +14,9 @@ interface AuthorizationParserInterface { - public function parse(ServerRequestInterface $request); + /** + * @param \Psr\Http\Message\ServerRequestInterface $request + * @return \Psr\Http\Message\ServerRequestInterface + */ + public function parse(ServerRequestInterface $request): ServerRequestInterface; } diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 657c0b7..d99c3e2 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -39,8 +39,10 @@ class AclMiddleware implements MiddlewareInterface public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; - /** @var AuthServiceInterface $service */ $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); + if (!$service instanceof AuthServiceInterface) { + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', ServiceConstants::AUTH_USERS_SERVICE)); + } if (!$service->auth($requestHandler, $request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); } diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index 41ab33e..e618954 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -15,7 +15,9 @@ use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; use Swoft\Auth\Constants\ServiceConstants; -use Swoft\Auth\Parser\AuthorizationHeaderParser; +use Swoft\Auth\Exception\AuthException; +use Swoft\Auth\Helper\ErrorCode; +use Swoft\Auth\Mapping\AuthorizationParserInterface; use Swoft\Bean\Annotation\Bean; use Swoft\Http\Message\Middleware\MiddlewareInterface; @@ -36,8 +38,10 @@ class AuthMiddleware implements MiddlewareInterface */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - /** @var AuthorizationHeaderParser $parser */ $parser = App::getBean(ServiceConstants::AUTH_REQUEST_HEADER_PARSER); + if (!$parser instanceof AuthorizationParserInterface) { + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', ServiceConstants::AUTH_REQUEST_HEADER_PARSER)); + } $request = $parser->parse($request); $response = $handler->handle($request); return $response; diff --git a/src/Parser/AuthorizationHeaderParser.php b/src/Parser/AuthorizationHeaderParser.php index 3b4493e..1e3593b 100644 --- a/src/Parser/AuthorizationHeaderParser.php +++ b/src/Parser/AuthorizationHeaderParser.php @@ -13,12 +13,16 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\App; use Swoft\Auth\Constants\AuthConstants; -use Swoft\Auth\Mapping\AuthHandleInterface; +use Swoft\Auth\Exception\AuthException; +use Swoft\Auth\Helper\ErrorCode; +use Swoft\Auth\Mapping\AuthorizationParserInterface; +use Swoft\Auth\Mapping\AuthHandlerInterface; +use Swoft\Auth\Parser\Handler\BasicAuthHandler; +use Swoft\Auth\Parser\Handler\BearerTokenHandler; use Swoft\Bean\Annotation\Value; use Swoft\Helper\ArrayHelper; -use Swoft\Http\Server\Parser\RequestParserInterface; -class AuthorizationHeaderParser implements RequestParserInterface +class AuthorizationHeaderParser implements AuthorizationParserInterface { /** * The parsers @@ -44,9 +48,11 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface $authValue = $request->getHeaderLine($this->headerKey); $type = $this->getHeadString($authValue); if (isset($this->mergeTypes()[$type])) { - /** @var AuthHandleInterface $handler */ $handler = App::getBean($this->mergeTypes()[$type]); - $request = $handler->parse($request); + if (!$handler instanceof AuthHandlerInterface) { + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthHandlerInterface', $this->mergeTypes()[$type])); + } + $request = $handler->handle($request); } return $request; } @@ -67,8 +73,8 @@ private function mergeTypes(): array public function defaultTypes(): array { return [ - BearerTokenParser::NAME => BearerTokenParser::class, - BasicAuthParser::NAME => BasicAuthParser::class + BearerTokenHandler::NAME => BearerTokenHandler::class, + BasicAuthHandler::NAME => BasicAuthHandler::class ]; } } diff --git a/src/Parser/BasicAuthParser.php b/src/Parser/Handler/BasicAuthHandler.php similarity index 87% rename from src/Parser/BasicAuthParser.php rename to src/Parser/Handler/BasicAuthHandler.php index cf9a03a..6f4695a 100644 --- a/src/Parser/BasicAuthParser.php +++ b/src/Parser/Handler/BasicAuthHandler.php @@ -8,11 +8,11 @@ * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ -namespace Swoft\Auth\Parser; +namespace Swoft\Auth\Parser\Handler; use Psr\Http\Message\ServerRequestInterface; use Swoft\Auth\Constants\AuthConstants; -use Swoft\Auth\Mapping\AuthHandleInterface; +use Swoft\Auth\Mapping\AuthHandlerInterface; use Swoft\Bean\Annotation\Bean; /** @@ -20,7 +20,7 @@ * @package Swoft\Auth\Parser * @Bean() */ -class BasicAuthParser implements AuthHandleInterface +class BasicAuthHandler implements AuthHandlerInterface { const NAME = 'Basic'; @@ -28,7 +28,7 @@ class BasicAuthParser implements AuthHandleInterface * @param \Psr\Http\Message\ServerRequestInterface $request * @return \Psr\Http\Message\ServerRequestInterface */ - public function parse(ServerRequestInterface $request): ServerRequestInterface + public function handle(ServerRequestInterface $request): ServerRequestInterface { $authHeader = $request->getHeaderLine(AuthConstants::HEADER_KEY) ?? ''; $basic = $this->parseValue($authHeader); diff --git a/src/Parser/BearerTokenParser.php b/src/Parser/Handler/BearerTokenHandler.php similarity index 87% rename from src/Parser/BearerTokenParser.php rename to src/Parser/Handler/BearerTokenHandler.php index 92b2ed1..6c61f68 100644 --- a/src/Parser/BearerTokenParser.php +++ b/src/Parser/Handler/BearerTokenHandler.php @@ -8,14 +8,14 @@ * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ -namespace Swoft\Auth\Parser; +namespace Swoft\Auth\Parser\Handler; use Psr\Http\Message\ServerRequestInterface; use Swoft\App; use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Constants\ServiceConstants; -use Swoft\Auth\Mapping\AuthHandleInterface; use Swoft\Auth\Mapping\AuthManagerInterface; +use Swoft\Auth\Mapping\AuthHandlerInterface; use Swoft\Bean\Annotation\Bean; /** @@ -23,7 +23,7 @@ * @package Swoft\Auth\Parser * @Bean() */ -class BearerTokenParser implements AuthHandleInterface +class BearerTokenHandler implements AuthHandlerInterface { const NAME = 'Bearer'; @@ -31,7 +31,7 @@ class BearerTokenParser implements AuthHandleInterface * @param \Psr\Http\Message\ServerRequestInterface $request * @return \Psr\Http\Message\ServerRequestInterface */ - public function parse(ServerRequestInterface $request): ServerRequestInterface + public function handle(ServerRequestInterface $request): ServerRequestInterface { $token = $this->getToken($request); /** @var AuthManagerInterface $manager */ diff --git a/src/AuthAccount.php b/test/Cases/Account/TestAccount.php similarity index 82% rename from src/AuthAccount.php rename to test/Cases/Account/TestAccount.php index 572c5d6..ca18a69 100644 --- a/src/AuthAccount.php +++ b/test/Cases/Account/TestAccount.php @@ -8,19 +8,18 @@ * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ -namespace Swoft\Auth; +namespace SwoftTest\Auth\Account; use Swoft\Auth\Bean\AuthResult; use Swoft\Auth\Mapping\AccountTypeInterface; use Swoft\Bean\Annotation\Bean; /** - * Class AuthAccount - * @package Swoft\Auth - * Here is an example, you should implement your own instance + * Class TestAccount + * @package SwoftTest\Auth * @Bean() */ -class AuthAccount implements AccountTypeInterface +class TestAccount implements AccountTypeInterface { /** * @param array $data Login data diff --git a/test/Cases/Parser/BasicAuthParserTest.php b/test/Cases/Handler/BasicAuthParserTest.php similarity index 92% rename from test/Cases/Parser/BasicAuthParserTest.php rename to test/Cases/Handler/BasicAuthParserTest.php index e9f66bb..a3c78a7 100644 --- a/test/Cases/Parser/BasicAuthParserTest.php +++ b/test/Cases/Handler/BasicAuthParserTest.php @@ -12,7 +12,6 @@ use Swoft\App; use Swoft\Auth\Constants\AuthConstants; -use Swoft\Auth\Parser\BasicAuthParser; use Swoft\Http\Message\Server\Request; use Swoft\Http\Server\Router\HandlerMapping; use SwoftTest\Auth\AbstractTestCase; @@ -36,9 +35,9 @@ protected function registerRoute() /** * @test - * @covers BasicAuthParser::parse() + * @covers BasicAuthHandler::handle() */ - public function testParser() + public function testHandle() { $username = 'user'; $password = '123'; diff --git a/test/Cases/Parser/BearerTokenParserTest.php b/test/Cases/Handler/BearerTokenParserTest.php similarity index 89% rename from test/Cases/Parser/BearerTokenParserTest.php rename to test/Cases/Handler/BearerTokenParserTest.php index d550a71..e0efbf4 100644 --- a/test/Cases/Parser/BearerTokenParserTest.php +++ b/test/Cases/Handler/BearerTokenParserTest.php @@ -13,7 +13,6 @@ use Swoft\App; use Swoft\Auth\AuthUserService; use Swoft\Auth\Constants\ServiceConstants; -use Swoft\Auth\Parser\BearerTokenParser; use Swoft\Http\Message\Server\Request; use Swoft\Http\Server\Router\HandlerMapping; use SwoftTest\Auth\AbstractTestCase; @@ -35,11 +34,10 @@ protected function registerRoute() /** * @test * @covers AuthManager::authenticateToken() - * @covers BearerTokenParser::parse() - * @covers AuthAccount::authenticate() + * @covers BearerTokenHandler::handle() * @covers AuthUserService::getSession() */ - public function testParse() + public function testHandle() { $jwt = new JWTTokenParserTest(); $token = $jwt->testGetToken(); diff --git a/test/Cases/Parser/JWTTokenParserTest.php b/test/Cases/Parser/JWTTokenParserTest.php index 3c57828..a9348e4 100644 --- a/test/Cases/Parser/JWTTokenParserTest.php +++ b/test/Cases/Parser/JWTTokenParserTest.php @@ -11,10 +11,10 @@ namespace SwoftTest\Auth\Parser; use Swoft\App; -use Swoft\Auth\AuthAccount; use Swoft\Auth\Bean\AuthSession; use Swoft\Auth\Parser\JWTTokenParser; use SwoftTest\Auth\AbstractTestCase; +use SwoftTest\Auth\Account\TestAccount; class JWTTokenParserTest extends AbstractTestCase { @@ -29,7 +29,7 @@ public function testGetToken() $session = new AuthSession(); $session->setIdentity(1); $session->setExpirationTime(time()+10); - $session->setAccountTypeName(AuthAccount::class); + $session->setAccountTypeName(TestAccount::class); $token = $parser->getToken($session); $this->assertStringStartsWith('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9', $token); return $token; diff --git a/test/config/properties/app.php b/test/config/properties/app.php index 151a8af..7d5c60b 100644 --- a/test/config/properties/app.php +++ b/test/config/properties/app.php @@ -16,7 +16,7 @@ ], 'beanScan' => [ 'Swoft\\Auth' => BASE_PATH . '/../src', - 'SwoftTest\\Auth\\'=> BASE_PATH .'/Cases/Base' + 'SwoftTest\\Auth\\Account'=> BASE_PATH .'/Cases/Account' ], 'I18n' => [ 'sourceLanguage' => '@root/resources/messages/', From 58c32de60c2e8b202c9f54f516a81e71006f88d9 Mon Sep 17 00:00:00 2001 From: ott321 Date: Wed, 6 Jun 2018 00:12:46 +0800 Subject: [PATCH 20/24] remove serviceConstants --- src/Bootstrap/CoreBean.php | 6 +++--- src/Constants/ServiceConstants.php | 20 -------------------- src/Middleware/AclMiddleware.php | 5 +++-- src/Middleware/AuthMiddleware.php | 5 +++-- src/Parser/Handler/BearerTokenHandler.php | 3 ++- test/Cases/Handler/BearerTokenParserTest.php | 2 +- 6 files changed, 12 insertions(+), 29 deletions(-) delete mode 100644 src/Constants/ServiceConstants.php diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index 09ff4c7..9bab679 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -31,14 +31,14 @@ class CoreBean implements BootBeanInterface public function beans() { return [ - ServiceConstants::AUTH_REQUEST_HEADER_PARSER => [ + AuthorizationHeaderParser::class=> [ 'class' => AuthorizationHeaderParser::class ], - ServiceConstants::AUTH_MANAGER=>[ + AuthManager::class=>[ 'class' => AuthManager::class, 'tokenParserClass'=>JWTTokenParser::class, ], - ServiceConstants::AUTH_USERS_SERVICE=>[ + AuthUserService::class=>[ 'class'=>AuthUserService::class ] ]; diff --git a/src/Constants/ServiceConstants.php b/src/Constants/ServiceConstants.php deleted file mode 100644 index 2d85f8c..0000000 --- a/src/Constants/ServiceConstants.php +++ /dev/null @@ -1,20 +0,0 @@ -getAttributes()['requestHandler'][2]['handler'] ?? ''; - $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); + $service = App::getBean(AuthUserService::class); if (!$service instanceof AuthServiceInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', ServiceConstants::AUTH_USERS_SERVICE)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', AuthUserService::class)); } if (!$service->auth($requestHandler, $request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index e618954..6d7886b 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -18,6 +18,7 @@ use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthorizationParserInterface; +use Swoft\Auth\Parser\AuthorizationHeaderParser; use Swoft\Bean\Annotation\Bean; use Swoft\Http\Message\Middleware\MiddlewareInterface; @@ -38,9 +39,9 @@ class AuthMiddleware implements MiddlewareInterface */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - $parser = App::getBean(ServiceConstants::AUTH_REQUEST_HEADER_PARSER); + $parser = App::getBean(AuthorizationHeaderParser::class); if (!$parser instanceof AuthorizationParserInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', ServiceConstants::AUTH_REQUEST_HEADER_PARSER)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', AuthorizationHeaderParser::class)); } $request = $parser->parse($request); $response = $handler->handle($request); diff --git a/src/Parser/Handler/BearerTokenHandler.php b/src/Parser/Handler/BearerTokenHandler.php index 6c61f68..94dcf7e 100644 --- a/src/Parser/Handler/BearerTokenHandler.php +++ b/src/Parser/Handler/BearerTokenHandler.php @@ -12,6 +12,7 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\App; +use Swoft\Auth\AuthManager; use Swoft\Auth\Constants\AuthConstants; use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Mapping\AuthManagerInterface; @@ -35,7 +36,7 @@ public function handle(ServerRequestInterface $request): ServerRequestInterface { $token = $this->getToken($request); /** @var AuthManagerInterface $manager */ - $manager = App::getBean(ServiceConstants::AUTH_MANAGER); + $manager = App::getBean(AuthManager::class); if ($token) { $res = $manager->authenticateToken($token); $request = $request->withAttribute(AuthConstants::IS_LOGIN, $res); diff --git a/test/Cases/Handler/BearerTokenParserTest.php b/test/Cases/Handler/BearerTokenParserTest.php index e0efbf4..e5392c7 100644 --- a/test/Cases/Handler/BearerTokenParserTest.php +++ b/test/Cases/Handler/BearerTokenParserTest.php @@ -25,7 +25,7 @@ protected function registerRoute() $router = App::getBean('httpRouter'); $router->get('/test', function (Request $request) { /** @var AuthUserService $service */ - $service = App::getBean(ServiceConstants::AUTH_USERS_SERVICE); + $service = App::getBean(AuthUserService::class); $session = $service->getSession(); return ['id'=>$session->getIdentity()]; }); From fe93ef90c87bce970cf80a1025c6a588decd2630 Mon Sep 17 00:00:00 2001 From: ott321 Date: Thu, 7 Jun 2018 18:18:27 +0800 Subject: [PATCH 21/24] change core bean key --- src/Bootstrap/CoreBean.php | 10 ++++++---- src/Middleware/AclMiddleware.php | 6 ++---- src/Middleware/AuthMiddleware.php | 4 ++-- src/Parser/Handler/BearerTokenHandler.php | 4 +--- test/Cases/Handler/BearerTokenParserTest.php | 4 ++-- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Bootstrap/CoreBean.php b/src/Bootstrap/CoreBean.php index 9bab679..7fc8329 100644 --- a/src/Bootstrap/CoreBean.php +++ b/src/Bootstrap/CoreBean.php @@ -12,7 +12,9 @@ use Swoft\Auth\AuthManager; use Swoft\Auth\AuthUserService; -use Swoft\Auth\Constants\ServiceConstants; +use Swoft\Auth\Mapping\AuthManagerInterface; +use Swoft\Auth\Mapping\AuthorizationParserInterface; +use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Auth\Parser\AuthorizationHeaderParser; use Swoft\Auth\Parser\JWTTokenParser; use Swoft\Bean\Annotation\BootBean; @@ -31,14 +33,14 @@ class CoreBean implements BootBeanInterface public function beans() { return [ - AuthorizationHeaderParser::class=> [ + AuthorizationParserInterface::class=> [ 'class' => AuthorizationHeaderParser::class ], - AuthManager::class=>[ + AuthManagerInterface::class=>[ 'class' => AuthManager::class, 'tokenParserClass'=>JWTTokenParser::class, ], - AuthUserService::class=>[ + AuthServiceInterface::class=>[ 'class'=>AuthUserService::class ] ]; diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 2d51fb9..d32a85c 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -14,8 +14,6 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; -use Swoft\Auth\AuthUserService; -use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthServiceInterface; @@ -40,9 +38,9 @@ class AclMiddleware implements MiddlewareInterface public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; - $service = App::getBean(AuthUserService::class); + $service = App::getBean(AuthServiceInterface::class); if (!$service instanceof AuthServiceInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', AuthUserService::class)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', AuthServiceInterface::class)); } if (!$service->auth($requestHandler, $request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index 6d7886b..bb18f0b 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -39,9 +39,9 @@ class AuthMiddleware implements MiddlewareInterface */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - $parser = App::getBean(AuthorizationHeaderParser::class); + $parser = App::getBean(AuthorizationParserInterface::class); if (!$parser instanceof AuthorizationParserInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', AuthorizationHeaderParser::class)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', AuthorizationParserInterface::class)); } $request = $parser->parse($request); $response = $handler->handle($request); diff --git a/src/Parser/Handler/BearerTokenHandler.php b/src/Parser/Handler/BearerTokenHandler.php index 94dcf7e..f48f0cd 100644 --- a/src/Parser/Handler/BearerTokenHandler.php +++ b/src/Parser/Handler/BearerTokenHandler.php @@ -12,9 +12,7 @@ use Psr\Http\Message\ServerRequestInterface; use Swoft\App; -use Swoft\Auth\AuthManager; use Swoft\Auth\Constants\AuthConstants; -use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Mapping\AuthManagerInterface; use Swoft\Auth\Mapping\AuthHandlerInterface; use Swoft\Bean\Annotation\Bean; @@ -36,7 +34,7 @@ public function handle(ServerRequestInterface $request): ServerRequestInterface { $token = $this->getToken($request); /** @var AuthManagerInterface $manager */ - $manager = App::getBean(AuthManager::class); + $manager = App::getBean(AuthManagerInterface::class); if ($token) { $res = $manager->authenticateToken($token); $request = $request->withAttribute(AuthConstants::IS_LOGIN, $res); diff --git a/test/Cases/Handler/BearerTokenParserTest.php b/test/Cases/Handler/BearerTokenParserTest.php index e5392c7..9d37a65 100644 --- a/test/Cases/Handler/BearerTokenParserTest.php +++ b/test/Cases/Handler/BearerTokenParserTest.php @@ -12,7 +12,7 @@ use Swoft\App; use Swoft\Auth\AuthUserService; -use Swoft\Auth\Constants\ServiceConstants; +use Swoft\Auth\Mapping\AuthServiceInterface; use Swoft\Http\Message\Server\Request; use Swoft\Http\Server\Router\HandlerMapping; use SwoftTest\Auth\AbstractTestCase; @@ -25,7 +25,7 @@ protected function registerRoute() $router = App::getBean('httpRouter'); $router->get('/test', function (Request $request) { /** @var AuthUserService $service */ - $service = App::getBean(AuthUserService::class); + $service = App::getBean(AuthServiceInterface::class); $session = $service->getSession(); return ['id'=>$session->getIdentity()]; }); From b2a43433729c4ed9ffecb86de28902078091b3c1 Mon Sep 17 00:00:00 2001 From: ott321 Date: Thu, 7 Jun 2018 22:02:48 +0800 Subject: [PATCH 22/24] fix bug --- src/Middleware/AclMiddleware.php | 2 +- src/Middleware/AuthMiddleware.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index d32a85c..08784c0 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -40,7 +40,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; $service = App::getBean(AuthServiceInterface::class); if (!$service instanceof AuthServiceInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', AuthServiceInterface::class)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', $service)); } if (!$service->auth($requestHandler, $request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index bb18f0b..ff10a7d 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -41,7 +41,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface { $parser = App::getBean(AuthorizationParserInterface::class); if (!$parser instanceof AuthorizationParserInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', AuthorizationParserInterface::class)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', $parser)); } $request = $parser->parse($request); $response = $handler->handle($request); From 3bd12972124967447136e1e7a796edf98e7b84eb Mon Sep 17 00:00:00 2001 From: ott321 Date: Sat, 9 Jun 2018 23:06:06 +0800 Subject: [PATCH 23/24] fix bug --- src/Middleware/AclMiddleware.php | 2 +- src/Middleware/AuthMiddleware.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 08784c0..3432622 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -40,7 +40,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; $service = App::getBean(AuthServiceInterface::class); if (!$service instanceof AuthServiceInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthServiceInterface', $service)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, 'AuthService should implement AuthServiceInterface'); } if (!$service->auth($requestHandler, $request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index ff10a7d..c4b521e 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -41,7 +41,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface { $parser = App::getBean(AuthorizationParserInterface::class); if (!$parser instanceof AuthorizationParserInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthorizationParserInterface', $parser)); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, 'AuthorizationParser should implement AuthorizationParserInterface'); } $request = $parser->parse($request); $response = $handler->handle($request); From 0796d94731599486e9900adea34e4a9d22366fc9 Mon Sep 17 00:00:00 2001 From: ott321 Date: Mon, 11 Jun 2018 11:05:58 +0800 Subject: [PATCH 24/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AuthManager.php | 8 ++++---- src/Middleware/AclMiddleware.php | 2 +- src/Middleware/AuthMiddleware.php | 4 +--- src/Parser/AuthorizationHeaderParser.php | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/AuthManager.php b/src/AuthManager.php index 881cf76..b695ab8 100644 --- a/src/AuthManager.php +++ b/src/AuthManager.php @@ -184,11 +184,11 @@ public function getTokenParser(): TokenParserInterface { if (!$this->tokenParser instanceof TokenParserInterface) { if (!App::hasBean($this->tokenParserClass)) { - throw new RuntimeException(sprintf('can`t find %s', $this->tokenParserClass)); + throw new RuntimeException('Can`t find tokenParserClass'); } $tokenParser = App::getBean($this->tokenParserClass); if (!$tokenParser instanceof TokenParserInterface) { - throw new RuntimeException(sprintf('%s need implements TokenParserInterface ', $this->tokenParserClass)); + throw new RuntimeException("TokenParser need implements Swoft\Auth\Mapping\TokenParserInterface "); } $this->tokenParser = $tokenParser; } @@ -202,11 +202,11 @@ public function getCacheClient() { if (!$this->cache instanceof CacheInterface) { if (!App::hasBean($this->cacheClass)) { - throw new RuntimeException(sprintf('can`t find %s', $this->cacheClass)); + throw new RuntimeException('Can`t find cacheClass'); } $cache = App::getBean($this->cacheClass); if (!$cache instanceof CacheInterface) { - throw new RuntimeException(sprintf('%s need implements CacheInterface ', $this->cacheClass)); + throw new RuntimeException('CacheClient need implements Psr\SimpleCache\CacheInterface'); } $this->cache = $cache; } diff --git a/src/Middleware/AclMiddleware.php b/src/Middleware/AclMiddleware.php index 3432622..83a25b9 100644 --- a/src/Middleware/AclMiddleware.php +++ b/src/Middleware/AclMiddleware.php @@ -40,7 +40,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler = $request->getAttributes()['requestHandler'][2]['handler'] ?? ''; $service = App::getBean(AuthServiceInterface::class); if (!$service instanceof AuthServiceInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, 'AuthService should implement AuthServiceInterface'); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, 'AuthService should implement Swoft\Auth\Mapping\AuthServiceInterface'); } if (!$service->auth($requestHandler, $request)) { throw new AuthException(ErrorCode::ACCESS_DENIED); diff --git a/src/Middleware/AuthMiddleware.php b/src/Middleware/AuthMiddleware.php index c4b521e..e45bf89 100644 --- a/src/Middleware/AuthMiddleware.php +++ b/src/Middleware/AuthMiddleware.php @@ -14,11 +14,9 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Swoft\App; -use Swoft\Auth\Constants\ServiceConstants; use Swoft\Auth\Exception\AuthException; use Swoft\Auth\Helper\ErrorCode; use Swoft\Auth\Mapping\AuthorizationParserInterface; -use Swoft\Auth\Parser\AuthorizationHeaderParser; use Swoft\Bean\Annotation\Bean; use Swoft\Http\Message\Middleware\MiddlewareInterface; @@ -41,7 +39,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface { $parser = App::getBean(AuthorizationParserInterface::class); if (!$parser instanceof AuthorizationParserInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, 'AuthorizationParser should implement AuthorizationParserInterface'); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, 'AuthorizationParser should implement Swoft\Auth\Mapping\AuthorizationParserInterface'); } $request = $parser->parse($request); $response = $handler->handle($request); diff --git a/src/Parser/AuthorizationHeaderParser.php b/src/Parser/AuthorizationHeaderParser.php index 1e3593b..0f6c786 100644 --- a/src/Parser/AuthorizationHeaderParser.php +++ b/src/Parser/AuthorizationHeaderParser.php @@ -50,7 +50,7 @@ public function parse(ServerRequestInterface $request): ServerRequestInterface if (isset($this->mergeTypes()[$type])) { $handler = App::getBean($this->mergeTypes()[$type]); if (!$handler instanceof AuthHandlerInterface) { - throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement AuthHandlerInterface', $this->mergeTypes()[$type])); + throw new AuthException(ErrorCode::POST_DATA_NOT_PROVIDED, sprintf('%s should implement Swoft\Auth\Mapping\AuthHandlerInterface', $this->mergeTypes()[$type])); } $request = $handler->handle($request); }