【发布时间】:2015-01-06 10:11:14
【问题描述】:
我正在 Symfony2 中构建一个 REST API 应用程序,并试图找到一种处理用户身份验证和授权的好方法。那里有很多解决方案,但到目前为止,它们都没有解决我所有的要求/顾虑。
该 API 将主要由 AngularJS SPA 使用,用户使用用户名和密码组合登录。让 GUI 用户能够:
- 使用用户名和密码登录
- 使用“记住我”复选框“永久”登录(可能是一周或类似时间)
- 在不同的浏览器中同时使用“记住我”(如 facebook)
- 从浏览器中删除 cookie 以注销用户
在服务器端,我想保持严格的 RESTful。我想出了一个似乎是我需要的解决方案,但我想确保我没有遗漏任何东西。
从服务器的角度来看成功登录尝试的工作流程:
- 使用用户名和密码在 /login API 端点接收 POST
- 生成新令牌并将其返回给客户端。在 db 中保存该令牌的哈希值。
- 每个令牌数据库条目必须有一个预定义的生命周期(在配置中设置)
- 到期日期时间必须存储在数据库中
- 旧的令牌哈希在过期时必须从数据库中删除(在登录尝试时或通过 cron)
- 令牌与用户是多对一的 - 用户可以在任何给定时间拥有多个活动令牌
- 每个令牌数据库条目必须有一个预定义的生命周期(在配置中设置)
从服务器的角度对登录用户的授权工作流程:
- 从授权标头中提取令牌
- 用户 ID 也可能包含在请求中,待定
- 哈希令牌并将其与数据库中每个用户的哈希值进行比较
- 如果其中一个 db 哈希与请求哈希匹配且未过期,则更新哈希过期并授权用户
从客户端 (GUI) 的角度来看成功登录尝试的工作流程:
- 使用用户名和密码向 /login API 端点发送 POST 请求
- 接收服务器生成的令牌。存储在浏览器的cookie中(使用js,服务器不设置cookie)
从客户端(GUI)的角度对登录用户进行授权的工作流程:
- 从cookie中读取token并在请求中设置Authorization头,例如Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- 始终从 cookie 中读取令牌,因为用户可能希望删除它以在浏览器中注销自己。
如果登录失败(cookie 删除或 401 响应)丢弃所有表单数据,删除 cookie 并重定向到登录屏幕。
显然,存储在客户端的 cookie 将在每次请求时传递给服务器,因为这就是 cookie 的作用,但服务器会忽略它。 cookie 仅供客户端使用。增加的带宽开销被认为可以忽略不计。
这个工作流程看起来好吗?我错过了什么吗?
【问题讨论】:
-
您是否考虑过使用本地存储而不是 Cookie。您选择 Cookie 的具体原因有哪些?
-
如果您不将 cookie 发送到服务器,那么为什么要使用它们?您不能使用本地存储或某些客户端方法来存储它。我们在我们的一个系统上进行了笔测试,标记的一件事是可以由客户端代码修改的 cookie。
-
通过“同时在不同的浏览器上使用“记住我”(如 facebook)”你的意思是记住我是共享的 - 即我在 Firefox 中勾选了它,所以 Chrome 应该使用它?如果是这样,我认为这是不可能的。 Cookie、缓存、本地存储,对每个浏览器都是本地的。
-
并且 cookie 将您限制为基于浏览器的客户端 - 如果您想在未来提供 API(对于本机应用程序),那就不好了。
-
还要确保添加 CSRF 保护
标签: angularjs rest symfony-2.6