Laravel5.8 + tymon/jwt

阅读: 评论:0

Laravel5.8 + tymon/jwt

Laravel5.8 + tymon/jwt

文章目录快捷导航

  • 第一章 概念普及
    • 1.1 JWT定义及其组成
      • 1.1.1 载荷(Payload)
      • 1.1.2 头部(Header)
      • 1.1.3 签名(签名)
    • 1.2 通过JWT 进行认证
  • 第二章 集成JWT到Laravel 5.8
    • 2.1 项目安装依赖
    • 2.2 项目配置
      • 2.2.1 发布配置文件
      • 2.2.2 生成密钥
    • 2.3 快速开始
      • 2.3.1 更新用户模型
      • 2.3.2 配置身份验证保护
      • 2.3.3 添加一些基本的认证路由
      • 2.3.4 创建AuthController
  • 第三章 测试
    • 3.1测试登录接口
    • 3.2 测试获取信息的接口

在JavaScript前端技术大行其道的今天,我们通常只需在后台构建API提供给前端调用,并且后端仅仅设计为给前端移动App调用。用户认证是Web应用的重要组成部分,基于API的用户认证有两个最佳解决方案 —— OAuth 2.0 和 JWT(JSON Web Token)。

第一章 概念普及

1.1 JWT定义及其组成

JWT(JSON Web Token)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名

1.1.1 载荷(Payload)

我们先将用户认证的操作描述成一个JSON对象。其中添加了一些其他的信息,帮助今后收到这个JWT的服务器理解这个JWT。

{"sub": "1","iss": "localhost:8000/auth/login","iat": 1451888119,"exp": 1454516119,"nbf": 1451888119,"jti": "37c107e4609ddbcc9c096ea5ee76c667"
}

这里面的前6个字段都是由JWT的标准所定义的。

  1. sub: 该JWT所面向的用户
  2. iss: 该JWT的签发者
  3. iat(issued at): 在什么时候签发的token
  4. exp(expires): token什么时候过期
  5. nbf(not before):token在此时间之前不能被接收处理
  6. jti:JWT ID为web token提供唯一标识
    这些定义都可以在标准中找到。

将上面的JSON对象进行base64编码可以得到下面的字符串:

eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4ODExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
这个字符串我们将它称作JWT的Payload(载荷)。

如果你使用Node.js,可以用Node.js的包base64url来得到这个字符串:

var base64url = require('base64url')var header = {"from_user": "B","target_user": "A"
}
console.log(base64url(JSON.stringify(header)))

注:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。

1.1.2 头部(Header)

JWT还需要一个头部,头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象:

{"typ": "JWT","alg": "HS256"
}

在这里,我们说明了这是一个JWT,并且我们所用的签名算法(后面会提到)是HS256算法。

对它也要进行Base64编码,之后的字符串就成了JWT的Header(头部):
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

1.1.3 签名(签名)

将上面的两个编码后的字符串都用句号.连接在一起(头部在前),就形成了:


最后,我们将上面拼接完的字符串用HS256算法进行加密。在加密的时候,我们还需要提供一个密钥(secret):

HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret
)

这样就可以得到我们加密后的内容:

wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4这一部分又叫做签名。

最后将这一部分签名也拼接在被签名的字符串后面,我们就得到了完整的JWT:

1.2 通过JWT 进行认证

JWT 是一个令牌(Token),客户端得到这个服务器返回的令牌后,可以将其存储到 Cookie 或 localStorage 中,此后,每次与服务器通信都要带上这个令牌,你可以把它放到 Cookie 中自动发送,但这样做不能跨域,所以更好的做法是将其放到 HTTP 请求头 Authorization 字段里面:
Authorization: Bearer
服务端收到这个 JWT 令牌后,就可以根据令牌值认定用户身份。

第二章 集成JWT到Laravel 5.8

2.1 项目安装依赖

composer require tymon/jwt-auth


安装完成后可以在项目根目录中的 composer.json 中看到如下内容

..."require": {"php": "^7.1.3","fideloper/proxy": "^4.0","laravel/framework": "5.8.*","laravel/tinker": "^1.0","tymon/jwt-auth": "^1.0" /* 刚下载的依赖*/},
...

2.2 项目配置

本文环境使用的是laravel 5.8 无需注册服务提供者,Laravel 5.4 及以下版本的用户需要手动配置一下

2.2.1 发布配置文件

在项目的控制台中输入

php artisan vendor:publish

然后根据提示回应对应的配置项编号即可。

成功之后可以看到项目目录/config/jwt.php的这个配置文件,你可以配置以下选项:

  • ttl:token有效期(分钟)
  • refresh_ttl:刷新token时间(分钟)
  • algo:token签名算法
  • user:指向User模型的命名空间路径
  • identifier:用于从token的sub中获取用户
  • require_claims:必须出现在token的payload中的选项,否则会抛出TokenInvalidException异常
  • blacklist_enabled:如果该选项被设置为false,那么我们将不能废止token,即使我们刷新了token,前一个token仍然有效
  • providers:完成各种任务的具体实现,如果需要的话你可以重写他们
  • User —— providers.user:基于sub获取用户的实现
  • JWT —— providers.jwt:加密/解密token
  • Authentication —— providers.auth:通过证书/ID获取认证用户
  • Storage —— providers.storage:存储token直到它们失效

2.2.2 生成密钥

通过如下命令

php artisan jwt:secret


成功后可以在.env中看到如下字段

JWT_SECRET=Wkgeflos6dLXPzt1f6fSB9qI4dmMpNgpoKezIsHxpzzKLSZjlXHSIvoKSsyCpL9H

2.3 快速开始

2.3.1 更新用户模型

首先,模型类需要在 User 模型实现TymonJWTAuthContractsJWTSubject接口和他的 2 个方法getJWTIdentifier()getJWTCustomClaims().

下面的示例应该让您了解它的外观。显然,您应该根据自己的需要进行任何更改。

<?phpnamespace App;use TymonJWTAuthContractsJWTSubject;
use IlluminateNotificationsNotifiable;
use IlluminateFoundationAuthUser as Authenticatable;class User extends Authenticatable implements JWTSubject
{use Notifiable;// Rest omitted for brevity/*** Get the identifier that will be stored in the subject claim of the JWT.** @return mixed*/public function getJWTIdentifier(){return $this->getKey();}/*** Return a key value array, containing any custom claims to be added to the JWT.** @return array*/public function getJWTCustomClaims(){return [];}
}

以下是根据上面的模板构建我的模型类

<?phpnamespace AppModels;use IlluminateDatabaseEloquentModel;
use IlluminateNotificationsNotifiable;
use IlluminateFoundationAuthUser as Authenticatable;
use TymonJWTAuthContractsJWTSubject;class UserModel extends Authenticatable implements JWTSubject
{protected $table = 't_users';protected $fillable = ['username','password'];public $timestamps = false;use Notifiable;// Rest omitted for brevity/*** Get the identifier that will be stored in the subject claim of the JWT.** @return mixed*/public function getJWTIdentifier(){return $this->getKey();}/*** Return a key value array, containing any custom claims to be added to the JWT.** @return array*/public function getJWTCustomClaims(){return [];}
}

2.3.2 配置身份验证保护

config/auth.php文件中,您需要进行一些更改以配置 Laravel 以使用jwt防护来支持您的应用程序身份验证。
对文件进行以下更改:

'defaults' => ['guard' => 'api','passwords' => 'users',
],...'guards' => ['api' => ['driver' => 'jwt','provider' => 'users',],
],...
// 由于我没使用系统自带的User类,所以下侧也要更改
'providers' => ['users' => ['driver' => 'eloquent',// 更改为我定义的模型的位置'model' => AppModelsUserModel::class,],// 'users' => [//     'driver' => 'database',//     'table' => 'users',// ],],

2.3.3 添加一些基本的认证路由

routes/api.php中配置一些带有权限认证的路由

Route::group(['middleware' => 'api','prefix' => 'auth'], function ($router) {Route::post('login', 'AuthController@login');Route::post('logout', 'AuthController@logout');Route::post('refresh', 'AuthController@refresh');Route::post('me', 'AuthController@me');});

2.3.4 创建AuthController

通过手动或者使用artisan工具命令时创建:

php artisan make:controller AuthController

然后添加如下内容

<?phpnamespace AppHttpControllers;use IlluminateSupportFacadesAuth;
use AppHttpControllersController;class AuthController extends Controller
{/*** Create a new AuthController instance.** @return void*/public function __construct(){$this->middleware('auth:api', ['except' => ['login']]);}/*** Get a JWT via given credentials.** @return IlluminateHttpJsonResponse*/public function login(){// 这里修改需要验证的字段$credentials = request(['email', 'password']);if (! $token = auth()->attempt($credentials)) {return response()->json(['error' => 'Unauthorized'], 401);}return $this->respondWithToken($token);}/*** Get the authenticated User.** @return IlluminateHttpJsonResponse*/public function me(){return response()->json(auth()->user());}/*** Log the user out (Invalidate the token).** @return IlluminateHttpJsonResponse*/public function logout(){auth()->logout();return response()->json(['message' => 'Successfully logged out']);}/*** Refresh a token.** @return IlluminateHttpJsonResponse*/public function refresh(){return $this->respondWithToken(auth()->refresh());}/*** Get the token array structure.** @param  string $token** @return IlluminateHttpJsonResponse*/protected function respondWithToken($token){return response()->json(['access_token' => $token,'token_type' => 'bearer','expires_in' => auth()->factory()->getTTL() * 60]);}
}

第三章 测试

3.1测试登录接口

{"access_token": &#Jpc3MiOiJodHRwOlwvXC90ZXN0MS5jb21cL2FwaVwvYXV0aFwvbG9naW4iLCJpYXQiOjE2MzMwMDc4MjIsImV4cCI6MTYzMzAxMTQyMiwibmJmIjoxNjMzMDA3ODIyLCJqdGkiOiIyMG8zczNHQkd4NnlnR2tuIiwic3ViIjoxLCJwcnYiOiI0MWRmODgzNGYxYjk4ZjcwZWZhNjBhYWVkZWY0MjM0MTM3MDA2OTBjIn0.josgI6pz8VLEjw2-etbjDL49Ju7xCnEMnJfd-zPAauc","token_type": "bearer","expires_in": 3600
}

成功拿到了。
有以下需要注意:

  1. config/api.php中定义的路由访问时 不能直接访问auth/**,必须添加api前缀,如api/auth/login,是由app/Providers/RouteServiceProvider.php决定的
  2. 图中可以看出我的数据库中密码为一串加密后的内容,但是提交的为123456,原因是采用laravel的auth机制来实现jwt在登录的时候会默认将密码进行Bcrypt加密,所以在注册时请直接将密码保存为该种加密方式

之后可以使用此令牌向您的应用程序发出经过身份验证的请求。

3.2 测试获取信息的接口

之前在api.php中定义了auth/me现在来携带Token进行测试


成功拿到了响应!~

本文发布于:2024-02-03 08:16:11,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170691937349783.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:tymon   jwt
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23