我们有一项基于用户名和密码来处理授权的服务。代替将用户名和密码作为调用的一部分,我们将其放置在SOAP header 中。
在典型情况下,Web服务在执行开始时会调用授权服务,以检查是否允许调用者调用它。问题在于这些Web服务中的某些服务相互调用,这意味着在每个子调用中都要检查用户的权限,这可能会非常昂贵。
我想做的是让授权服务在第一个调用之后返回安全 token 。然后,Web服务可以不必在本地调用安全 header ,而不必每次都调用授权服务。
安全标题看起来像这样(修剪C#代码以说明基本概念):
public sealed class SecurityHeader : SoapHeader
{
public string UserId; // Encrypted
public string Password; // Encrypted; Just realized this field isn't necessary [thanks CJP]
public DateTime TimeStamp; // Used for calculating header Expiry
public string SecurityToken;
}
总体思路是,每次调用都会检查SecurityHeader。如果存在,并且尚未过期,并且SecurityToken有效,则Web方法将正常进行。否则,它将返回错误,或者将尝试重新授权并生成新的SecurityHeader
SecurityToken基于UserId,Password和TimeStamp的盐化哈希值。每天都要更换盐,以防止重播。
我确实看到的一个问题是,用户可能有权访问Web Service A,但没有访问Web Service B的权限。如果他调用A并收到一个安全 token ,就目前的情况而言,这意味着B如果他使用,将允许他通过相同的 token 。我必须对其进行更改,以便安全 token 仅在Web Service到Web Service之间有效,而在User to Web Service范围内有效。如果用户调用A调用B,则应该确定,但是如果用户调用Service A然后再调用Service D,则应该确定。解决该问题的方法是将一个公用 key (或一组 key )分配给逻辑上相关的服务。 (即,如果客户可以做A,那么在逻辑上他也可以做B)。
或者,我必须将用户的整个权限集编码为安全 header 的一部分。我将不得不调查开销是多少。
编辑:
好几个人提到过要研究其他安全方案,例如WS-Security和SAML等。我已经有了。实际上,我是从WS-Security获得这个想法的。问题在于其他方案没有提供我需要的功能(在没有中间数据库的情况下缓存授权信息并防止重放)。如果有人知道这样做的方案,那么我会乐意使用它。另外,这与身份验证无关。这是由我无法控制的另一种机制处理的。
如果事实证明没有办法缓存授权数据,则意味着我只需要承担每个级别的授权开销。
最佳答案
方案的根本问题是您没有使用标准框架或实现。这与方案本身的任何优点无关。
原因很简单,安全性(特别是加密)非常非常复杂,几乎不可能正确解决。使用可靠,易于理解和证明的通用工具。
有关WS-Security的更多信息,请参见: http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss 。
大多数框架(.NET/JavaEE等)都将在一定程度上为WS-Security提供内置支持。
如果您认为您的方案在某种程度上要比标准更好,我建议您将其编写为论文并提交给同行评审(以及引用实现),但不要使用它来保护应用程序的安全。
编辑以响应OP编辑:
我认为您有点混淆了身份验证和授权的角色,这很容易实现...
方案中的安全 token (或类似证书)的作用是验证消息的发送者-基本上,发送者应该是谁。正如您正确指出的那样,身份验证并不暗示要授予发件人访问哪些基础资源。
授权是您获取经过身份验证的发件人并应用一组权限以便可以限制访问范围的过程。通常,框架默认情况下不会进行授权,您必须通过创建某种形式的ACL或通过扩展某种“安全管理器”类型的界面来启用它。
实际上,其想法是身份验证层告诉您谁在尝试访问页面A,然后由您决定该人是否有权访问页面A。
您绝不应该在消息本身中存储有关权限的信息-接收者应针对每条消息针对其ACL(或数据库或其他内容)验证权限。如果有人弄清楚如何修改邮件,这将限制您的访问量。
关于web-services - 此Web服务安全方案有哪些潜在问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/153329/