当同一个laravel项目有多端(移动端、管理端……)都需要使用jwt做用户验证时,如果用户表有多个(一般都会有),就需要做token隔离,不然会发生移动端的token也能请求管理端的问题,造成用户越权。
会引发这个问题的原因是laravel的jwt token默认只会存储数据表的主键的值,并没有区分是那个表的。所以只要token里携带的id在你的用户表中都存在,就会导致越权验证。
我们来看看laravel的jwt token 的原貌:
1
2
3
4
5
6
7
8
9
{
"iss"
:
"http://your-request-url"
,
"iat"
: 1558668215,
"exp"
: 1645068215,
"nbf"
: 1558668215,
"jti"
:
"xakidug7k0jewgdi"
,
"sub"
: 1,
"prv"
:
"92d5e8eb1b38ccd11476896c19b0e44512b2aacd"
}
携带数据的是sub字段,其他字段是jwt的验证字段。
我们只看到sub的值为1,并没有说明是那个表或是哪个验证器的。这个token通过你碰碰车作文的验证中间件时,你使用不同的guard就能拿到对应表id为1的用户(了解guard请查看laravel的文档)。
想要解决用户越权的问题,我们只要在token上带上我们的自定义字段,用来区分是哪个表或哪个验证器生成的,然后再编写自己的中间件验证我们的自定义字段是否符合我们的预期。
我们知道要使用jwt验证,用户模型必须要实现jwtsubject的接口(代码取自jwt文档):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
namespace
app;
u
tymon\jwtauth\contracts\jwtsubject;
u
illuminate\notifications\notifiable;
u
illuminate\foundation\auth\ur
as
authenticatable;
class
ur
extends
authenticatable
implements
jwtsubject
{
u
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
[];
}
}
我们可以看看实现的这两个方法的作用:
getjwtidentifier的:获取会储存到jwt声明中的标识,其实就是要我们返回标识用户表的主键字段名称,这里是返回的是主键’id’,getjwtcustomclaims:返回包含要添加到jwt声明中的自定义键值对数组,这里返回空数组,没有添加任何自定义信息。接下来我们就可以在实现了getjwtcustomclaims方法的用户模型中添加我们的自定义信息了。
管理员模型:
1
2
3
4
5
6
7
8
9
/**
* 额外在 jwt 载荷中增加的自定义内容
*
* @return array
*/
public
function
getjwtcustomclaims()
{
return
[
'role'
=>
'admin'
];
}
移动端用户模型:
1
2
3
4
5
6
7
8
9
/**
* 额外在 jwt 载荷中增加的自定义内容
*
* @return array
*/
public
function
getjwtcustomclaims()
{
return
[
'role'
=>
'ur'
];
}
这里添加了一个角色名作为用户标识。
这样管理员生成的token会像这样:
1
2
3
4
5
6
7
8
9
10
{
"iss"
:
"http://your-request-url"
,
"iat"
: 1558668215,
"exp"
: 1645068215,
"nbf"
: 1558668215,
"jti"
:
"xakidug7k0jewgdi"
,
"sub"
: 1,
"prv"
:
"92d5e8eb1b38ccd11476896c19b0e44512b2aacd"
,
"role"
:
"admin"
}
移动端用户生成的token会像这样:
1
2
3
4
5
6
7
8
9
10
{
"iss"
:
"http://your-request-url"
,
"iat"
: 1558668215,
"exp"
: 1645068215,
"nbf"
: 1558668215,
"jti"
:
"xakidug7k0jewgdi"
,
"sub"
: 1,
"prv"
:
"92d5e8eb1b38ccd11476896c19b0e44512b2aacd"
,
"role"
:
"ur"
}
我们可以看到这里多了一个我们自己加的role字段,并且对应我们的用户模型。
接下来我们自己写一个中间件,解析token后判断是否是我们想要的角色,对应就通过,不对应就报401就好了。
这里提供一个可全局使用的中间件(推荐用在用户验证中间件前):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
/**
* created by phpstorm.
* ur: wlalala
* date: 2019-04-17
* time: 13:55
*/
namespace
app\http\middleware;
u
closure;
u
symfony\component\httpkernel\exception\unauthorizedhttpexception;
u
tymon\jwtau八月的图片带字图片th\exceptions\jwtexception;
u
tymon\jwtauth\http\middleware\bamiddleware;
class
jwtroleauth
extends
bamiddleware
{
/幼儿园毕业感言**
* handle an incoming request.
*
* @param $request
* @param closure $next
* @param null $role
* @return mixed
*/
public
function
handle(
$request
, closure
$next
,
$role
= null)
{
try
{
// 解析token角色
$token_role
=
$this
->auth->partoken()->getclaim(
'role'
);
}
catch
(jwtexception
$e
) {
/**
* token解析失败,说明请求中没有可用的token。
* 为了可以全局使用(不需要token的请求也可通过),这里让请求继续。
* 因为这个中间件的责职只是校验token里的角色。
*/
return
$next
(
$request
);
}
// 判断token角色。
if
(
$token_role
!=
$role
) {
throw
new
unauthorizedhttpexception(
'jwt-auth'
,
'ur role error'
);
}
return
$next
(
$request
);
}
}
在app/http/kernel.php中注册中间件:
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
思修试题* the application's route middleware.
*
* the middleware may be assigned to groups or ud individually.
*
* @var array
*/
protected
$routemiddleware
= [
// ...省略 ...
// 多表jwt验证校验
'jwt.role'
=> \app\http\middleware\jwtroleauth::
class
,
];
接下来在需要用户验证的路由组中添加我们的中间件:
1
2
3
4
5
6
7
8
9
10
11
12
13
route::group([
'middleware'
=> [
'jwt.role:admin'
,
'jwt.auth'
],
],
function
(
$router
) {
// 管理员验证路由
// ...
});
route::group([
'middleware'
=> [
'jwt.role:u孙炎明r'
,
'jwt.auth'
],
],
function
(
$router
) {
// 移动端用户验证路由
// ...
});
至此完成jwt多表用户验证隔离。
本文发布于:2023-04-07 19:21:20,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/7b860e500fb8f1eed71959ec9da16b75.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Laravel jwt 多表验证隔离.doc
本文 PDF 下载地址:Laravel jwt 多表验证隔离.pdf
留言与评论(共有 0 条评论) |