Tom*_*ock 9 security optimization authorization http jwt
JWT是一种确保数据发送给用户并且不会被篡改的好方法,但这会带来一些艰难的选择.目前,我处于两难选择之中,即在授权数据中存储授权数据并仅为授权触摸数据库一次,或者只是存储用户ID并检查每个请求与数据库的服务器的授权级别.
使这个如此艰难的选择的原因是该应用程序使用多个授权级别,这使得base64编码的URL非常长且笨重(参见下面可以预期存储为授权级别的内容).
另一方面,要获得授权,必须在数据库中进行两次查找.
所以我的问题如下:通过向服务器发送权限,每个请求的额外开销是否值得避免在每次请求时查找权限的麻烦?
作为旁注; 在权限更改的情况下,查找数据库方法的好处是不需要用户再次登录(请参阅post).
"perms": {
"roles": [
{
"name": "Admin",
"id": 1,
"assigned": true
},
{
"name": "Webmaster",
"id": 8,
"assigned": true
}
],
"actions": [
{
"id": 1,
"name": "cms-edit",
"parameters": null,
"parameterized": null
},
{
"id": 9,
"name": "admin-syslog",
"parameters": null,
"parameterized": null
},
{
"id": 10,
"name": "admin-debug",
"parameters": null,
"parameterized": null
},
{
"id": 12,
"name": "member-list-extended",
"parameters": null,
"parameterized": null
},
{
"id": 2,
"name": "cms-list",
"parameters": null,
"parameterized": null
},
{
"id": 3,
"name": "cms-add",
"parameters": null,
"parameterized": null
},
{
"id": 5,
"name": "member-list",
"parameters": null,
"parameterized": null
},
{
"id": 7,
"name": "member-view",
"parameters": null,
"parameterized": null
},
{
"id": 8,
"name": "member-edit",
"parameters": null,
"parameterized": null
}
]
Run Code Online (Sandbox Code Playgroud)
Aka*_*kar 15
你的第一个问题:
通过向服务器发送权限,每个请求的额外开销是否值得避免在每次请求时查找权限的麻烦?
回答:
让我们看一下jwt.io提供的关于何时使用JWT的描述:
授权:这是使用JWT的最常见方案.一旦用户登录,每个后续请求将包括JWT,允许用户访问该令牌允许的路由,服务和资源.Single Sign On是一种现在广泛使用JWT的功能,因为它的开销很小,并且能够在不同的域中轻松使用.
这意味着一旦用户登录,您需要在服务器端生成令牌.
它包含:
一旦客户端向服务器请求或发送数据,服务器首先检查给定令牌是否有效并且是否已知,然后检查角色是否满足访问某个资源的标准.
所有角色/访问数据都可以在系统启动时读取一次并保存在内存中.此外,客户端具有的角色只能从数据库中.这样,客户端日志阅读,一旦你有没有后续的数据库访问,因此,有很大的性能提升.
另一方面,如果客户端请求数据或想要执行操作,则需要一种身份验证机制来评估传递的令牌是否获得了执行此操作所需的角色.
这样我们解决了数据库的麻烦,加上我们消除了向客户端暴露太多信息的危险(即使客户端无法篡改数据,它也可以读取数据!)
请注意:https://jwt.io/introduction
请注意,使用签名令牌,令牌中包含的所有信息都会向用户或其他方公开,即使他们无法更改.这意味着您不应该在令牌中放置秘密信息.
参见A3(敏感数据暴露):https://www.owasp.org/index.php/Top_10-2017_Top_10
最后:如果客户端空闲时间过长或故意注销,也会使令牌无效.
后续问题:
许可的情况改变了数据库中的查找方法,其好处是不需要用户再次登录
回答:
根据服务器的基础结构,您可以编写刷新机制(如果角色更新,服务器生成新令牌并将其与生成的答案一起发送到客户端,使旧的无效,客户端仅使用最近的令牌并覆盖旧的)或在服务器端添加一些状态,如客户端会话:
消除令牌上的角色/权限.您最好为客户端生成会话并在服务器端提供会话角色/权限.客户端获取可以进行身份验证的会话令牌(通常是id).一旦权限/角色发生变化,我们就必须做两件事:
同样,每个后续请求都将在内存中执行角色/权限检查,并且不需要数据库通信,而客户端只有一个小会话令牌(或您的JWT).因此,角色/权限更改对客户端是透明的(不需要重新连接),我们消除了JWT刷新要求.
取决于你如何解释效率。在谈论资源效率时,请记住您的 JWT 是在每个请求上传输的。因此,如果您有一个带有细粒度访问控制列表 (ACL) 的大型应用程序,并且您总是在每个请求-响应中来回访问这些列表,那么这肯定会花费您几千字节,具体取决于您发出的请求数量。