laravel 5.7 安装 jwt-auth,jwt-auth 文档翻译

laravel 5.7 安装 jwt-auth(默认安装的是 0.5.12 版本)

github 地址:
	https://github.com/tymondesigns/jwt-auth

旧版文档:
	https://github.com/tymondesigns/jwt-auth/wiki

新版文档:
	https://jwt-auth.readthedocs.io/en/develop/(这个是 1.0.0 版本的文档)

安装(Installation)
	安装包
		composer require tymon/jwt-auth

	添加服务提供者
		编辑 config/app.php,在 "providers" 添加:
			'Tymon\JWTAuth\Providers\JWTAuthServiceProvider',

	添加 Facades
		编辑 config/app.php,在 "alias" 添加:
		'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
		'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',

	发布配置文件:
		php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

	生成 secret key
		php artisan jwt:generate

	安装完成后,执行 php artisan jwt:generate,会报错:
		1.Method Tymon\JWTAuth\Commands\JWTGenerateCommand::handle() does not exist
			解决方法,这个需要修改源码:
				编辑 vendor/tymon/jwt-auth/src/Commands/JWTGenerateCommand.php,新增:
				    /**
				     * Compatiblity with Laravel >= 5.5
				     */
				    public function handle()
				    {
				        $this->fire();
				    }

		2.如果未添加服务提供者,直接执行该命令,可能也会报错!
			There are no commands defined in the "jwt" namespace
			解决方法:
				就是上面的添加服务提供者

配置(Configuration)
	secret(secret key) - 秘钥
		用来签名 token 的秘钥。作者将秘钥与 Laravel 的 APP_KEY 分开,以便开发者可以独立地修改它们。
		提供了一个 artisan 命令,为我们生成一个随机秘钥。(php artisan jwt:generate)

	ttl(token time to live) - token 生存时间
		token 的有效时间,以分钟为单位。建议尽可能设置短点,尤其是当我们也使用 token 刷新机制。

	refresh_ttl(refresh time to live) - refresh 生存时间
		可以刷新 token 的有效时间,以分钟为单位。例如,如果设置为 2周,那么只能在 2周 内,刷新对应的 token,否则将会抛出 TokenExpiredException 异常。如果超过了刷新的有效时间,必须生成一个全新的 token,这意味着用户需要重新登录。

	注:ttl 和 refresh_ttl,用于保持用户的登录状态

	algo(hashing algorithm) - hash 算法
		用于签名 token 的算法,保留默认值即可

	user(user model path) - 用户模型路径
		应该指向我们项目的 User 类的命名空间路径

	identifier(user identifier) - 用户标识
		从 token 的主题声明中,根据什么标识来检索用户(一般是 id)

	required_claims(required claims)
		这些声明必须存在于 token 的 payload 中,否则将抛出 TokenInvalidException 异常(会检测 token 的 payload 是否存在这些声明)

	blacklist_enabled(blacklist enabled)
		如果设置为 false,将无法使 token 失效。虽然我们仍然可以刷新令牌,但是之前的令牌仍旧有效,因此这样做非常不安全。但对于非常简单的实现,可能不需要额外的开销(刷新 token 等),我们可以配置它。

	providers
		jwt-auth 包已经有一些具体实现,可用来实现各种需求。只要遵循相关接口,我们就可以覆盖这些具体实现。
	providers.user
		指定基于主题声明,来查找用户的实现。

	providers.jwt
		完成 token 的编码和解码的繁重工作

	providers.auth
		通过凭证或 id 来认证用户

	providers.storage
		用于驱动黑名单,并存储 token 直到过期。

创建 tokens(Creating Tokens)
	jwt-auth 包为我们提供了创建 token 的多种方法。有简单的方法,如果你想更好的控制,也有更进一步的方法。

	开箱即用(out of box),有许多必须的声明,虽然这些都可以配置:
		sub(Subject) - 包含 token 的标识符(默认是用户 ID)
		iat(Issued At) - token 发布时间(unix 时间戳)
		exp(Expiry) - token 过期日期(unix 时间戳)
		nbf(Not Before) - 可以使用 token 的最早时间点(unix 时间戳)
		iss(Issuer) - token 发布者(默认为请求的 url)
		jti(JWT Id) - token 的唯一标识符(sub 和 iat 声明的 md5 值)
		aud(Audience) - token 的目标受众(默认不需要)
	也允许自定义声明。稍后会介绍。

	创建一个基于用户凭证的 token
		创建 token 的最常用方法是,通过用户的登录凭证,来认证用户。如果认证成功,则返回一个与该用户相关的 token。例如,假设我们有一个 Laravel AuthenticateController

			use JWTAuth;
			use Tymon\JWTAuth\Exceptions\JWTException;

			class AuthenticateController extends Controller
			{
			    public function authenticate(Request $request)
			    {
			        // grab credentials from the request
			        $credentials = $request->only('email', 'password');

			        try {
			            // attempt to verify the credentials and create a token for the user
			            if (! $token = JWTAuth::attempt($credentials)) {
			                return response()->json(['error' => 'invalid_credentials'], 401);
			            }
			        } catch (JWTException $e) {
			            // something went wrong whilst attempting to encode the token
			            return response()->json(['error' => 'could_not_create_token'], 500);
			        }

			        // all good so return the token
			        return response()->json(compact('token'));
			    }
			}

	创建一个基于用户对象的 token
		我们可以跳过用户认证,只传递一个用户对象

			$user = User::first();
			$token = JWTAuth::fromUser($user);

		上面的 2 个方法也有第二个参数,可以传递一个 '自定义声明' 的数组

			$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
			JWTAuth::attempt($credentials, $customClaims);
			JWTAuth::fromUser($user, $customClaims);

		在解码 token 时,这些自定义声明,将和其他声明一起提供。
		注意:添加大量的自定义声明,将增加 token 的大小

	创建一个基于任意你喜欢的内容的 token
		作者给我们提供了对底层类和方法的访问,来提供高级的、可自定义的功能。
		示例使用了内建的 'Tymon\JWTAuth\PayloadFactory' 实例(或者使用 JWTFactory 门面):

			$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
			$payload = JWTFactory::make($customClaims);
			$token = JWTAuth::encode($payload);

		也可以在 'Tymon\JWTAuth\PayloadFactory' 实例上链式调用声明(或者使用 JWTFactory 门面):

			$payload = JWTFactory::sub(123)->aud('foo')->foo(['bar' => 'baz']);
			$token = JWTAuth::encode($payload);

认证(Authentication)
	一旦用户使用他们的凭证登录,下一步将使用 token 发起一个后续请求,来检索用户详情,以便我们可以将其显示为已登录。

	使用内置方法,通过 http 发起认证请求,我们需要设置一个 Authorization 请求头,如下所示:
		Authorization: Bearer {yourtokenhere}

	Apache 用户需要注意:
	Apache 好像会丢弃 Authorization 请求头,如果该请求头不是 base64 编码的 user/pass 组合。为了解决此问题,我们可以在 apache 配置文件中添加一下内容:
		RewriteEngine On
		RewriteCond %{HTTP:Authorization} ^(.*)
		RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

	或者,我们可以通过在查询字符串中包含 token 来实现:
		http://api.mysite.com/me?token={yourtokenhere}

	为了从请求中获取 token,我们可以:
		// 会设置 token 到返回的对象中
		JWTAuth::parseToken();
		// 接着,我们可以继续链式调用方法
		$user = JWTAuth::parseToken()->authenticate();

	为了获取 token 的值,我们可以调用:
		$token = JWTAuth::getToken();
	如果设置了一个 token,则会返回 token,否则(为方便起见),它将使用上述方法,尝试从请求中解析 token,如果没有设置 token 或 没有 token 可以被解析,最终返回 false。

	当然,如果在我们的程序中有其他入口点,我们也可以根据需要手动设置 token。例如:
		JWTAuth::setToken('foo.bar.baz');

	从 token 中检索认证过的用户
		public function getAuthenticatedUser()
		{
			try {
				if(! $user = JWTAuth::parseToken()->authenticate()){
					return response()->json('user_not_found', 404);
				}
			} catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
				return response()->json(['token_expired'], $e->getStatusCode());
			} catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
				return response()->json(['token_invalid'], $e->getStatusCode());
			} catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
				return response()->json(['token_absent'], $e->getStatusCode());
			}
			return response()->json(compact('user'));
		}

	如果不喜欢内联捕获多个异常的方法,我们可以随意使用 Laravel 添加全局异常处理程序。

	在 app/Exceptions/Handler.php 中,将下面代码添加到 render() 方法:
		public function render($request, Exception $e)
		{
			if ($e instanceof Tymon\JWTAuth\Exceptions\TokenExpiredException) {
				return response()->json(['token_expired'], $e->getStatusCode());
			} else if ($e instanceof Tymon\JWTAuth\Exceptions\TokenInvalidException) {
				return response()->json(['token_invalid'], $e->getStatusCode());
			}

			return parent::render($request, $e);
		}

	中间件和过滤器
		如果我们使用的是 Laravel 5,可以使用内置的 2 个中间件:
			GetUserFromToken
				检查请求头和查询字符串(正如上面解释过的)是否存在 token,并尝试解码 token。如上所述,同样的事件被触发。

			RefreshToken
				此中间件将再次尝试从请求中解析 token,然后将刷新 token(从而使旧 token 失效),并将其作为下一次响应的一部分返回。这实际上产生了单个使用 token 流,如果 token 被泄露,这种方式会减少攻击,因为它仅对单个请求有效。

		为了使用这 2 个中间件,我们需要将它们注册到 app/Http/Kernel.php 里的 $routeMIddleware 属性:
			protected $routeMiddleware = [
				...
				'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',
				'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',
			];

附 2 篇优秀文章(没看,但应该不错):
	https://laravel-chiona.org/articles/10885/full-use-of-jwt
	https://laravel-china.org/articles/17883


-----------------------------------------------------------------------------
后记:
	发现不指定版本号,安装的是 0.5.12 版本
	我们项目中,打算使用最新版:1.0.0-rc.3

	composer require tymon/jwt-auth:1.0.0-rc.3

	文档地址:
		https://jwt-auth.readthedocs.io/en/develop/

	翻译:
		Laravel 安装:
			通过 composer 安装:
				composer require tymon/jwt-auth:1.0.0-rc.3

			添加服务提供者:
				编辑 config/app.php,在 "providers" 添加:
					Tymon\JWTAuth\Providers\LaravelServiceProvider::class,

			发布配置文件:
				php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

			生成 secret key:
				php artisan jwt:secret
				.env 文件下,会新增 JWT_SECRET

		快速开始:
			更新用户模型:
				User 模型,实现 Tymon\JWTAuth\Contracts\JWTSubject,并添加 getJWTIdentifier() 和 getJWTCustomClaims() 2 个方法

				例如:
					getKey();
					    }

					    /**
					     * Return a key value array, containing any custom claims to be added to the JWT.
					     *
					     * @return array
					     */
					    public function getJWTCustomClaims() 	// 这个
					    {
					        return [];
					    }
					}

			配置 Auth guard:
				config/auth.php
				'defaults' => [
				    'guard' => 'api',			// 使用 api guard
				    'passwords' => 'users',
				],

				...

				'guards' => [
				    'api' => [					// 定义 api guard
				        'driver' => 'jwt',		// 使用 jwt
				        'provider' => 'users',
				    ],
				],

			中间件:
				auth:api

			控制器内使用:
				middleware('auth:api', ['except' => ['login']]);		// 中间件
				    }

				    /**
				     * Get a JWT via given credentials.
				     *
				     * @return \Illuminate\Http\JsonResponse
				     */
				    public function login()
				    {
				        $credentials = request(['email', 'password']);

				        if (! $token = auth()->attempt($credentials)) {			// api 认证,通过后得到 token
				            return response()->json(['error' => 'Unauthorized'], 401);
				        }

				        return $this->respondWithToken($token);					// 返回 token 给客户端
				    }

				    /**
				     * Get the authenticated User.
				     *
				     * @return \Illuminate\Http\JsonResponse
				     */
				    public function me()
				    {
				        return response()->json(auth()->user());		// 通过 api 认证得到用户信息
				    }

				    /**
				     * Log the user out (Invalidate the token).
				     *
				     * @return \Illuminate\Http\JsonResponse
				     */
				    public function logout()
				    {
				        auth()->logout();		// api 退出

				        return response()->json(['message' => 'Successfully logged out']);
				    }

				    /**
				     * Refresh a token.
				     *
				     * @return \Illuminate\Http\JsonResponse
				     */
				    public function refresh()
				    {
				        return $this->respondWithToken(auth()->refresh());		// 刷新 token,返回给客户端
				    }

				    /**
				     * Get the token array structure.
				     *
				     * @param  string $token
				     *
				     * @return \Illuminate\Http\JsonResponse
				     */
				    protected function respondWithToken($token)
				    {
				        return response()->json([
				            'access_token' => $token,
				            'token_type' => 'bearer',
				            'expires_in' => auth()->factory()->getTTL() * 60
				        ]);
				    }
				}

			认证请求:
				通过 HTTP 给服务器发送 token,有以下几种方法:
					认证头:
						Authorization: Bearer eyJhbGciOiJIUzI1NiI...

					查询字符串参数:
						http://example.dev/me?token=eyJhbGciOiJIUzI1NiI...

					Post 参数:
						暂无

					Cookies:
						暂无

					Laravel 路由参数:
						暂无

		Auth Guard:
			Auth Guard 实例上,可用以下方法:
				attempt() - 通过用户身份凭证,来认证用户
					$token = auth()->attempt($credentials);
					成功返回 jwt token,失败返回 null

				login() - 传递一个用户实例,来登录用户
					$user = User::first();
					$token = auth()->login($user);

				user() - 获取当前认证的用户
					$user = auth()->user();
					如果用户未认证,返回 null

				userOrFail() - 获取当前认证的用户,否则抛出异常
					try {
					    $user = auth()->userOrFail();
					} catch (\Tymon\JWTAuth\Exceptions\UserNotDefinedException $e) {
					    // do something
					}

				logout() - 用户退出,会使当前 token 失效,并删除认证的用户
					auth()->logout();

					// 第一个参数传递 true,强制 token 添加到 "forever" 黑名单
					auth()->logout(true);

				refresh() - 刷新 token,会令当前 token 失效,生成一个新 token
					$newToken = auth()->refresh();

					// 第一个参数传递 true,强制此 token 添加到 "forever" 黑名单
					// 第二个参数传递 true,会重置新 token 的声明(claims)
					$newToken = auth()->refresh(true, true);

				invalidate() - 使当前 token 失效(添加到黑名单)
					auth()->invalidate();

					// 第一个参数传递 true,强制 token 添加到 "forever" 黑名单
					auth()->invalidate(true);

				tokenById() - 基于给定用户 ID,获取 token
					$token = auth()->tokenById(32451);

				payload() - 获取原生的 JWT payload
					$payload = auth()->payload();

					// 之后可以直接访问声明
					$payload->get('sub');		// 123
					$payload['jti'];			// 'xxx'
					$payload('exp');			// 123456
					$payload->toArray();		// ['sub' => 123, 'exp' => 123456, 'jti' => 'xxx']

				validate() - 认证用户身份凭证
					if(auth()->validate($credentials)){
						// 认证通过
					}

			进一步使用:
				添加自定义声明:
					$token = auth()->claims(['foo' => 'bar'])->attempt($credentials);

				显示设置 token:
					$user = auth()->setToken('xxx')->user();

				显示设置请求实例:
					$user = auth()->setRequest($request)->user();

				覆盖 token ttl:
					$token = auth()->setTTL(7200)->attempt($credentials);

		配置:
			和旧版本的配置不同,官方还未提供文档,看 config/jwt.php 文件注释即可

 

你可能感兴趣的:(php,laravel框架)