diff --git a/.env.example b/.env.example index 0148bbd..d166dcc 100644 --- a/.env.example +++ b/.env.example @@ -47,4 +47,10 @@ PUSHER_APP_SECRET= YUNPIAN_API_KEY= #微信 WEIXIN_APPID= -WEIXIN_SECRET= \ No newline at end of file +WEIXIN_SECRET= + +# php artisan jwt:secret +JWT_SECRET= +# 单位分钟 +JWT_TTL=60 +JWT_REFRESH_TTL=20160 \ No newline at end of file diff --git a/app/Http/Controllers/Api/AuthorizationsController.php b/app/Http/Controllers/Api/AuthorizationsController.php index 774fe95..537b356 100644 --- a/app/Http/Controllers/Api/AuthorizationsController.php +++ b/app/Http/Controllers/Api/AuthorizationsController.php @@ -2,12 +2,18 @@ namespace App\Http\Controllers\Api; +use App\Http\Requests\Api\AuthorizationRequest; use App\Http\Requests\Api\SocialAuthorizationRequest; use App\Models\User; use Laravel\Socialite\Facades\Socialite; class AuthorizationsController extends Controller { + /** + * @param $type + * @param SocialAuthorizationRequest $request + * @throws \ErrorException + */ public function socialStore($type, SocialAuthorizationRequest $request) { if (!in_array($type, ['weixin'])) { @@ -44,6 +50,58 @@ class AuthorizationsController extends Controller } break; } - return $this->response->array(['token' => $user->id]); + + $token = \Auth::guard('api')->fromUser($user); + + return $this->respondWithToken($token)->setStatusCode(201); + } + + /** + * @param AuthorizationRequest $request + * @throws \ErrorException + */ + public function store(AuthorizationRequest $request) + { + $username = $request->get('username'); + filter_var($username, FILTER_VALIDATE_EMAIL) ? $credentials['email'] = $username : $credentials['phone'] = $username; + $credentials['password'] = $request->get('password'); + if (!$token = \Auth::guard('api')->attempt($credentials)) { + return $this->response->errorUnauthorized('用户名或密码错误'); + } + return $this->respondWithToken($token)->setStatusCode(201); + } + + /** + * @return mixed + * @throws \ErrorException + */ + public function update() + { + $token = \Auth::guard('api')->refresh(); + return $this->respondWithToken($token); + } + + /** + * @return \Dingo\Api\Http\Response + */ + public function destroy() + { + \Auth::guard('api')->logout(); + return $this->response->noContent(); + } + + + /** + * @param $token + * @return mixed + * @throws \ErrorException + */ + protected function respondWithToken($token) + { + return $this->response->array([ + 'access_token' => $token, + 'token_type' => 'Bearer', + 'expires_in' => \Auth::guard('api')->factory()->getTTL() * 60 + ]); } } diff --git a/app/Http/Requests/Api/AuthorizationRequest.php b/app/Http/Requests/Api/AuthorizationRequest.php new file mode 100644 index 0000000..d739564 --- /dev/null +++ b/app/Http/Requests/Api/AuthorizationRequest.php @@ -0,0 +1,31 @@ + 'required|string', + 'password' => 'required|string|min:6', + ]; + } +} diff --git a/app/Models/User.php b/app/Models/User.php index daf8852..a7ed908 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -8,13 +8,14 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Facades\Auth; use Spatie\Permission\Traits\HasRoles; +use Tymon\JWTAuth\Contracts\JWTSubject; /** * Class User * @property string avatar * @package App\Models */ -class User extends Authenticatable +class User extends Authenticatable implements JWTSubject { use Notifiable { notify as protected laravelNotify; @@ -42,6 +43,16 @@ class User extends Authenticatable 'password', 'remember_token', ]; + public function getJWTIdentifier() + { + return $this->getKey(); + } + + public function getJWTCustomClaims() + { + return []; + } + /** * @return string */ diff --git a/composer.json b/composer.json index 9eb01f5..ba7f336 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "socialiteproviders/weixin": "^4.0", "spatie/laravel-permission": "~2.7", "summerblue/administrator": "~1.1", + "tymon/jwt-auth": "1.0.0-rc.2", "viacreative/sudo-su": "~1.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 76dee20..d5284f4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "588439ee64e05cdd8901cf40a7966df1", + "content-hash": "e9a02a045616c7c6a7078c57f181b2f8", "packages": [ { "name": "cakephp/chronos", @@ -1784,8 +1784,66 @@ "time": "2018-05-17T13:42:07+00:00" }, { + "name": "lcobucci/jwt", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/0b5930be73582369e10c4d4bb7a12bac927a203c", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=5.5" + }, + "require-dev": { + "mdanter/ecc": "~0.3.1", + "mikey179/vfsstream": "~1.5", + "phpmd/phpmd": "~2.2", + "phpunit/php-invoker": "~1.1", + "phpunit/phpunit": "~4.5", + "squizlabs/php_codesniffer": "~2.3" + }, + "suggest": { + "mdanter/ecc": "Required to use Elliptic Curves based algorithms." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Otávio Cobucci Oblonczyk", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "time": "2017-09-01T08:23:26+00:00" + }, + { "name": "league/flysystem", - "version": "1.0.45", + "version": "1.0.45", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", @@ -1865,7 +1923,7 @@ "sftp", "storage" ], - "time": "2018-05-07T08:44:23+00:00" + "time": "2018-05-07T08:44:23+00:00" }, { "name": "league/fractal", @@ -2259,8 +2317,71 @@ "time": "2017-01-23T04:29:33+00:00" }, { + "name": "namshi/jose", + "version": "7.2.3", + "source": { + "type": "git", + "url": "https://github.com/namshi/jose.git", + "reference": "89a24d7eb3040e285dd5925fcad992378b82bcff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/namshi/jose/zipball/89a24d7eb3040e285dd5925fcad992378b82bcff", + "reference": "89a24d7eb3040e285dd5925fcad992378b82bcff", + "shasum": "" + }, + "require": { + "ext-date": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-spl": "*", + "php": ">=5.5", + "symfony/polyfill-php56": "^1.0" + }, + "require-dev": { + "phpseclib/phpseclib": "^2.0", + "phpunit/phpunit": "^4.5|^5.0", + "satooshi/php-coveralls": "^1.0" + }, + "suggest": { + "ext-openssl": "Allows to use OpenSSL as crypto engine.", + "phpseclib/phpseclib": "Allows to use Phpseclib as crypto engine, use version ^2.0." + }, + "type": "library", + "autoload": { + "psr-4": { + "Namshi\\JOSE\\": "src/Namshi/JOSE/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Nadalin", + "email": "alessandro.nadalin@gmail.com" + }, + { + "name": "Alessandro Cinelli (cirpo)", + "email": "alessandro.cinelli@gmail.com" + } + ], + "description": "JSON Object Signing and Encryption library for PHP.", + "keywords": [ + "JSON Web Signature", + "JSON Web Token", + "JWS", + "json", + "jwt", + "token" + ], + "time": "2016-12-05T07:27:31+00:00" + }, + { "name": "nesbot/carbon", - "version": "1.29.2", + "version": "1.29.2", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", @@ -2304,7 +2425,7 @@ "datetime", "time" ], - "time": "2018-05-29T15:23:46+00:00" + "time": "2018-05-29T15:23:46+00:00" }, { "name": "nikic/php-parser", @@ -3902,8 +4023,64 @@ "time": "2018-04-26T10:06:28+00:00" }, { - "name": "symfony/polyfill-php70", + "name": "symfony/polyfill-php56", "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php56.git", + "reference": "af98553c84912459db3f636329567809d639a8f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/af98553c84912459db3f636329567809d639a8f6", + "reference": "af98553c84912459db3f636329567809d639a8f6", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-util": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php56\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2018-04-26T10:06:28+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", @@ -3958,11 +4135,63 @@ "portable", "shim" ], - "time": "2018-04-26T10:06:28+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { + "name": "symfony/polyfill-util", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-util.git", + "reference": "1a5ad95d9436cbff3296034fe9f8d586dce3fb3a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/1a5ad95d9436cbff3296034fe9f8d586dce3fb3a", + "reference": "1a5ad95d9436cbff3296034fe9f8d586dce3fb3a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Util\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony utilities for portability of PHP codes", + "homepage": "https://symfony.com", + "keywords": [ + "compat", + "compatibility", + "polyfill", + "shim" + ], + "time": "2018-04-26T10:06:28+00:00" + }, + { "name": "symfony/process", - "version": "v3.4.11", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -4007,7 +4236,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-05-16T08:49:21+00:00" + "time": "2018-05-16T08:49:21+00:00" }, { "name": "symfony/routing", @@ -4273,6 +4502,81 @@ "time": "2017-11-27T11:13:29+00:00" }, { + "name": "tymon/jwt-auth", + "version": "1.0.0-rc.2", + "source": { + "type": "git", + "url": "https://github.com/tymondesigns/jwt-auth.git", + "reference": "d5220f6a84cbb8300f6f2f0f20aa908d072b4e4b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tymondesigns/jwt-auth/zipball/d5220f6a84cbb8300f6f2f0f20aa908d072b4e4b", + "reference": "d5220f6a84cbb8300f6f2f0f20aa908d072b4e4b", + "shasum": "" + }, + "require": { + "illuminate/auth": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*", + "illuminate/contracts": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*", + "illuminate/http": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*", + "illuminate/support": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*", + "lcobucci/jwt": "^3.2", + "namshi/jose": "^7.0", + "nesbot/carbon": "^1.0", + "php": "^5.5.9 || ^7.0" + }, + "require-dev": { + "cartalyst/sentinel": "2.0.*", + "illuminate/console": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*", + "illuminate/database": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*", + "illuminate/routing": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*", + "mockery/mockery": ">=0.9.9", + "phpunit/phpunit": "~4.8 || ~6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "1.0-dev" + }, + "laravel": { + "aliases": { + "JWTAuth": "Tymon\\JWTAuth\\Facades\\JWTAuth", + "JWTFactory": "Tymon\\JWTAuth\\Facades\\JWTFactory" + }, + "providers": [ + "Tymon\\JWTAuth\\Providers\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Tymon\\JWTAuth\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sean Tymon", + "email": "tymon148@gmail.com", + "homepage": "https://tymon.xyz", + "role": "Developer" + } + ], + "description": "JSON Web Token Authentication for Laravel and Lumen", + "homepage": "https://github.com/tymondesigns/jwt-auth", + "keywords": [ + "Authentication", + "JSON Web Token", + "auth", + "jwt", + "laravel" + ], + "time": "2018-02-07T20:55:14+00:00" + }, + { "name": "viacreative/sudo-su", "version": "1.1.0", "source": { @@ -6265,7 +6569,8 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "dingo/api": 15 + "dingo/api": 15, + "tymon/jwt-auth": 5 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/config/api.php b/config/api.php index ae7fdda..f7e5ae0 100644 --- a/config/api.php +++ b/config/api.php @@ -168,7 +168,7 @@ return [ */ 'auth' => [ - + 'jwt' => \Dingo\Api\Auth\Provider\JWT::class ], /* diff --git a/config/auth.php b/config/auth.php index 087bbb3..4f251b4 100644 --- a/config/auth.php +++ b/config/auth.php @@ -42,7 +42,7 @@ return [ ], 'api' => [ - 'driver' => 'token', + 'driver' => 'jwt', 'provider' => 'users', ], ], diff --git a/routes/api.php b/routes/api.php index aa0a65d..ac1b26b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -33,6 +33,16 @@ $api->version('v1', ['namespace' => 'App\Http\Controllers\Api'], function ($api) $api->post('socials/{social_type}/authorizations', 'AuthorizationsController@socialStore') ->name('api.socials.authorizations.store'); + // 登录 + $api->post('authorizations', 'AuthorizationsController@store') + ->name('api.authorizations.store'); + + // 刷新token + $api->put('authorizations/current', 'AuthorizationsController@update') + ->name('api.authorizations.update'); + // 删除token + $api->delete('authorizations/current', 'AuthorizationsController@destroy') + ->name('api.authorizations.destroy'); });