laravel中jwt的使用(详细)
首先是理论,随后实现
JWT 出场
JWT 还有个好处,那就是你可以不用在服务端存储认证信息(比如 token),完全由客户端提供,服务端只要根据 JWT 自身提供的解密算法就可以验证用户合法性,而且这个过程是安全的。
JWT 数据结构
JWT 最后的形式就是个字符串,它由头部、载荷与签名这三部分组成,中间以「.」分隔。像下面这样:
头部
头部以 JSON 格式表示,用于指明令牌类型和加密算法。形式如下,表示使用 JWT 格式,加密算法采用 HS256,这是最常用的算法,除此之外还有很多其他的。
载荷
用来存储服务器需要的数据,比如用户信息,例如姓名、性别、年龄等,要注意的是重要的机密信息最好不要放到这里,比如密码等。
另外,JWT 还规定了 7 个字段供开发者选用。
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
这部分信息也是要用 Base64 编码的。
签名
签名有一个计算公式。
使用HMACSHA256算法计算得出,这个方法有两个参数,前一个参数是 (base64 编码的头部 + base64 编码的载荷)用点号相连,后一个参数是自定义的字符串密钥,密钥不要暴露在客户端,近应该服务器知道。
使用方式
了解了 JWT 的结构和算法后,那怎么使用呢?假设我这儿有个网站。
1、在用户登录网站的时候,需要输入用户名、密码或者短信验证的方式登录,登录请求到达服务端的时候,服务端对账号、密码进行验证,然后计算出 JWT 字符串,返回给客户端。
2、客户端拿到这个 JWT 字符串后,存储到 cookie 或者 浏览器的 LocalStorage 中。
3、再次发送请求,比如请求用户设置页面的时候,在 HTTP 请求头中加入 JWT 字符串,或者直接放到请求主体中。
4、服务端拿到这串 JWT 字符串后,使用 base64的头部和 base64 的载荷部分,通过HMACSHA256算法计算签名部分,比较计算结果和传来的签名部分是否一致,如果一致,说明此次请求没有问题,如果不一致,说明请求过期或者是非法请求。
1.composer安装
composer require laravel/passport=~9.0
2.具体实现
首先数据库迁移
php artisan make:migration create_users_table --create=apiuser
随后迁移,生成数据表,保存token数据
php artisan migrate
数据库字段
Schema::create('apiuser', function (Blueprint $table) {
$table->id();
$table->string('username',100)->comment('账号');
$table->string('password',100)->comment('密码');
$table->unsignedTinyInteger('click')->default(0)->comment('请求次数');
$table->timestamps();
});
3.生成客户端授权码
要记录下来啊
php artisan passport:install
4.修改config/auth.php文件中的api配置
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
//解决接口登录
'api' => [
'driver' => 'passport',
'provider' => 'users',
// 'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \App\models\Apiuser::class,
],
],
令牌的有效期
注意
修改接口账号模型
在其User类 use Laravel\Passport\HasApiTokens;
// token认证有效期2小时
Passport::tokensExpireIn(now()->addHour(2));
// 刷新token认证有效期30天
Passport::refreshTokensExpireIn(now()->addDays(30));
解决auth在接口中登录没有attempt问题
具体代码关键
public function login(Request $request) {
// 表单验证
// 异步捕获 ajax 和 接口会用
try {
// 验证不通过跳转到 首页 需要自定义异常走向,错误信息要让自己来确定
$this->validate($request, [
'username' => 'required',
'password' => 'required'
]);
} catch (\Exception $exception) {
return response()->json(['status' => 1000, 'msg' => '账号或密码不能为空'], 400);
}
// 查看对象中可用的方法
//dump(get_class_methods());
$bool=auth()->guard('web')->attempt($request->all());
// dd($bool);
// return $bool;
// 账号登录成功
if ($bool) {
// 生成token
// 得到用户模型对象
$userModel = auth()->guard('web')->user();
// 判断接口当天是否超过2000次
if ($userModel->click > env('APINUM')) {
return response()->json(['status' => 1002, 'msg' => '当天请求次数超上限'], 500);
}
// dd(1);
// 生成token 保存在服务器端1份,给客户返回1份
$token = $userModel->createToken('api')->accessToken;
// dd($token);
// 让当请求次数加 1 数据一致
$aa=$userModel->increment('click'); //set click=click+1
// dd($aa);
$data = [
'expire' => 7200,
'token' => $token
];
return response()->json($data);
} else {
return response()->json(['status' => 1001, 'msg' => '账号或密码不正确'], 401);
}
}
坑注意,效果
Postman 测试
**
接口安全验证
使用了jwt进行验证
需要对接口路由绑定中间件,前提是auth.php文件中的一定要把api节点中的driver更换为passport
postman测试
转载:
https://juejin.cn/post/6862498355579682823