保护有状态的 Web 服务
Posted
技术标签:
【中文标题】保护有状态的 Web 服务【英文标题】:Securing a stateful web service 【发布时间】:2011-06-22 03:43:15 【问题描述】:我们正计划开发一层 REST 服务来公开托管在遗留系统上的服务。这些服务将被经典的 Web 应用程序和原生手机应用程序使用。
此旧系统的安全性要求初始用户名 + 密码身份验证(此过程可能需要 5 到 10 秒)。在初始身份验证之后,将返回一个时间受限的令牌。然后必须将此令牌包含在所有进一步的请求中,否则请求将被拒绝。
由于安全要求,不能在 REST 服务层之外返回旧版安全令牌。这意味着 REST 服务层需要将此令牌保存在某种形式的用户会话中,否则每次调用旧系统时都需要重复昂贵的用户名 + 密码身份验证过程。
REST 服务层将使用 Java 6 + Spring 3 + Spring Security 3 堆栈实现。乍一看,这个设置看起来运行良好:基于 Spring 的 REST 服务将使用相当标准的 Spring Security 配置进行保护,遗留安全令牌将存储在用户的 HTTP 会话中,每次调用都将使用用户的会话并将其发送到旧系统。
但问题是:REST 客户端如何发送必要的数据,以便正确检索用户的 HTTP 会话?这通常由 Web 浏览器使用 JSESSIONID cookie 透明地完成,但此过程不涉及浏览器。当然,REST 客户端可以将 cookie 管理添加到他们的代码中,但是对于所有 Spring RestTemplate、iPhone、BlackBerry 和 android 客户端来说,这是一件容易的事吗?
另一种方法是绕过 REST 服务层的 HTTP 会话并使用其他形式的用户会话,可能使用数据库,这将使用 REST 客户端通过 HTTP 标头或简单的请求查询。那么问题就变成了,如何配置 Spring Security 以使用这种替代会话机制而不是标准的 Servlet HttpSession?
当然,我不是第一个处理这种情况的人。我错过了什么?
谢谢!
【问题讨论】:
【参考方案1】:cookies 没有什么神奇之处。他们只是strings in HTTP headers。任何体面的客户端 API 都可以处理它们,尽管许多需要显式配置才能启用 cookie 处理。
使用 cookie 的替代方法是将 JSESSIONID 放入 URL。我对 spring-security 一无所知,但似乎这实际上是至少某些类型的 URL 请求的默认值,除非 disable-url-rewriting
明确设置为 true 。不过,这可以视为 security weakness。
【讨论】:
同意。这就是饼干被发明的目的。使用它们 我同意使用 cookie 是显而易见的解决方案。我想我的问题更多地在于这是否是将 Spring 的 RestTemplate 或 iPhone / Android / 其他本机移动应用程序与后端 REST 服务集成的标准解决方案。例如,使用 RestTemplate 管理 cookie 不是开箱即用的,需要额外的代码。也许我错过了另一种广泛使用的用户状态管理方案。或者也许我只是在不必要地使事情复杂化:)【参考方案2】:不幸的是,身份验证存在很大问题——在网络标准和浏览器实现方面有点盲点。您是对的,cookie 不被视为“RESTful”,而是纯粹主义者,但即使在功能齐全的浏览器上,避免也需要相当多的技巧,如本文所述:Rest based authentication。
很遗憾,我没有做过任何移动开发,所以我无法建议最好的折衷方案是什么。您可能希望首先检查每个目标平台支持支持哪些身份验证模型。特别是,两个主要选项是:
HTTP 身份验证(理想情况下是“摘要”,而不是“基本”) Cookie一种可能性是提供both 选项。从技术或安全的角度来看显然不是理想的,但在可用性方面可能有优点。
【讨论】:
以上是关于保护有状态的 Web 服务的主要内容,如果未能解决你的问题,请参考以下文章
仅使用 Spring Security 自定义令牌无状态保护 REST 控制器,同时保持常规状态完整 Web 登录正常工作