【发布时间】:2018-05-06 03:28:54
【问题描述】:
在浏览器(网站后端)中运行的 Angular 4 应用程序,显示来自特定用户拥有的服务器数据。 服务器:PHP+MySQL、Zend Framework 3 + Doctrine ORM
命名:
-
access_token:生命周期短(1 分钟),允许访问个人资源,携带 user_id,base64 编码,json web token 规范有效。 -
refresh_token:长寿命(1 周)允许在不提供凭据的情况下检索新的 access_token,存储在数据库中,如果需要可以由管理员撤销。
使用refresh_tokens的要点是登录时间长于access_token短寿命(如果refresh_token到期时间在每次用户授权发生时更新,则可能永远),用户只需要在不活动的情况下提供凭据超过refresh_token 一生。
刷新令牌存储在数据库中,因此可以轻松撤销。
1。浏览器尝试进行身份验证
请求:
- 用户名和密码
- 发送到 /api/auth
回应:
用户名和密码已通过数据库验证和检查
如果有效:
-
access_token的生成时间为 60 秒 -
user_id被编码为 access_token -
生成
refresh_token(随机字符串)并保存到db,过期时间1周,(access_token中不包含refresh_token,是单独的key) - HTTP 200 正常
如果无效:
- HTTP 401 未经授权
之后的行动
如果有效:
- access_token 和
refresh_token存储在浏览器中(身份验证服务的私有成员变量,浏览器的本地存储)。
看起来将refresh_token 存储在本地存储中不是一个好主意 - 但这允许“让我保持登录状态”。如果仅将每个浏览器会话存储在私有成员变量中,则用户每次打开浏览器时都需要登录。有什么想法吗?
如果无效:
- 显示错误,建议重试
2。浏览器向服务器请求受保护的数据
请求:
- 发送 access_token
- 到/api/resource
回应:
- 如果access_token有效,则发送json数据,HTTP 200 OK
- 如果 access_token 无效(例如无法解码),HTTP 400 错误请求
- 如果 access_token 过期,HTTP 401 Unauthorized
回应后的行动:
- 如果 HTTP 200:数据显示
- 如果 HTTP 400:重定向到登录页面
- 如果 HTTP 401:使用存储在浏览器中的 refresh_token 重试获取新的 access_token
3。重试使用 refresh_token 进行身份验证(在 HTTP 401 Unauthorized 之后)
请求:
- access_token
- 刷新令牌
回应:
- 验证
access_token(除过期时间外的所有内容,使用 \Firebase\JWT) - 针对数据库验证
refresh_token(从access_token、字符串和过期时间解码的user_id)
如果有效:
生成新的refresh_token,保存到数据库,更新ttl(或者应该是同一个token,只更新ttl?) 生成新的 access_token HTTP 200 正常
如果无效:
HTTP 401 未经授权
响应后的操作:
如果有效:
- 在浏览器中存储新的 access_key 和 refresh_key
- 使用新的 access_key 重试之前的资源请求
如果无效:
- 显示登录页面
问题
我不喜欢的关键点是access_token和refresh_token存储在同一个地方,发送方式相同。也许还有其他方法可以做到这一点?
- 这个逻辑合理吗?
- 是否存在任何安全漏洞,假设这发生在 Web 应用程序中?
- 我应该将这两个令牌都存储在浏览器的本地存储中吗?
- 应该将
refresh_token编码为access_token吗?如果它们仍然保存在同一个地方,看起来它可能被合并到 access_token 中。有什么理由不这样做? - 我应该什么时候更新
refresh_tokenlifetime? - 任何开源项目都可以看到类似的身份验证?
- 还有其他建议吗?
【问题讨论】:
标签: angular security oauth-2.0 authorization jwt