使用客户端cookies的REST API身份验证和授权工作流程

6
我正在使用Symfony2构建REST API应用程序,并尝试找到一种处理用户身份验证和授权的好方法。有许多解决方案,但迄今为止没有一个解决了我所有的要求/担忧。
该API主要由AngularJS SPA使用,其中用户使用用户名和密码组合登录。重要的是使GUI用户能够:
- 使用用户名和密码登录 - 使用“记住我”复选框永久登录(可能是一周或类似的时间) - 在同时使用不同浏览器时使用“记住我”(如Facebook) - 从浏览器中删除cookie以注销用户
在服务器端,我希望保持严格的RESTful。我想出了一个解决方案,它似乎是我需要的,但我想确保我没有漏掉任何东西。
从服务器的角度来看,成功登录尝试的工作流程如下:
1. 在/login API端点上接收带有用户名和密码的POST请求 2. 生成新令牌并将其返回给客户端。在db中保存该令牌的哈希值。 - 每个令牌db条目必须具有预定义的生命周期(在配置中设置) - 过期日期时间必须存储在db中 - 当令牌过期时(在登录尝试或通过cron)必须从db中删除旧的令牌哈希 - 令牌与用户是多对一的关系-用户可以在任何给定时间拥有多个活动令牌 3. 活动令牌
从服务器的角度来看,已登录用户的授权工作流程如下:
1. 从Authorization标头中提取令牌 - 可能还包括请求的用户ID,待定 2. 哈希令牌并将其与db中每个用户的哈希值进行比较 3. 如果db哈希之一与请求哈希匹配且未过期,则更新哈希过期并授权用户
从客户端(GUI)的角度来看,成功登录尝试的工作流程如下:
1. 向/login API端点发送带有用户名和密码的POST请求 2. 接收服务器生成的令牌。使用js将其存储在浏览器中的cookie中(服务器不设置cookie)
从客户端(GUI)的角度来看,已登录用户的授权工作流程如下:
1. 从cookie中读取令牌并在请求中设置Authorization标头,例如Authorization:Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== - 总是从cookie中读取令牌,因为用户可能想要删除它以在浏览器中注销自己。
如果登录失败(cookie已删除或401响应),则丢弃所有表单数据,删除cookie并重定向到登录屏幕。

显然,客户端存储的cookie会在每个请求中传递给服务器,因为这就是cookie的作用,但服务器会忽略它。cookie只是为了客户端而存在的。增加的带宽开销被认为是可以忽略不计的。

这个工作流程看起来还好吗?我有没有漏掉什么?


你有没有考虑使用本地存储代替Cookies?你选择使用Cookies的具体原因是什么? - Wayne Ellery
如果你不将cookie发送到服务器,那么为什么要使用它们?难道你不能使用本地存储或一些客户端方法来存储这些信息吗?我们对系统进行了一次针对测试,其中一个被标记的问题是cookie可以被客户端代码修改。 - Lee Willis
“在不同的浏览器中同时使用“记住我”(如Facebook)”是指您是否希望“记住我”功能可以共享 - 例如,我在Firefox中勾选了“记住我”,那么Chrome也应该使用它吗?如果是这样,我认为这是不可能的。因为Cookie、缓存和本地存储都是每个浏览器本地独立的。” - Lee Willis
而且Cookie会限制你只能使用基于浏览器的客户端,如果以后要为原生应用提供API就不太好了。 - Lee Willis
1
请确保您添加CSRF保护。 - Wayne Ellery
我需要使用cookies,因为“从浏览器中删除cookies以注销用户”是一个要求。为什么客户端可以修改cookies是不好的?我可以手动在firebug中修改任何cookie,我认为这不是一个安全问题?Cookies不限制我只能使用基于浏览器的客户端。授权标头被使用。Cookies只是客户端的一部分。我可以使用本地存储代替,但是cookies被广泛使用并且终端用户也期望使用它们(尽管我可能会重新考虑这个问题)。CSRF保护不是必需的,因为服务器不读取cookie。 - tomasp
1个回答

1
我做了一个名为WebApiSecure的项目,它使用Json Web Tokens(JWT)进行授权 - BasicBearer。我相信它完成了你描述的大部分功能,例如允许令牌过期并添加用户ID或角色。它可能会帮助你实现你想要做的事情。
它是使用Web Api 2构建的,前端可以基于AngularJS或JQuery。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接