2008-09-30 245 views
5

我们有一个基于用户名和密码处理授权的服务。我们不把用户名和密码作为调用的一部分,而是放在SOAP头中。这个WebService安全方案有哪些潜在的问题?

在典型的情况下,Web服务在执行开始时调用授权服务,以检查是否允许调用者调用它。问题在于这些Web服务中的一些互相调用,这意味着在每个子调用中都会检查用户的权限,而且这可能非常昂贵。

我想要做的是让授权服务在第一次调用后返回一个安全令牌。然后,Web服务不必每次都调用授权服务,而是可以在本地验证安全标头。

安全头看起来像这样(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服务A,但不能访问Web服务B.如果他调用A并收到安全令牌,就像现在这样,这意味着B会让他如果他使用相同的标记。我必须对其进行更改,以便安全令牌仅从Web服务到Web服务而不是Web服务即用户有效。如果用户调用A调用B,应该是可以的,但如果用户调用服务A然后调用服务D,则不是OK。解决此问题的方法是将一个公用密钥(或一组密钥)分配给逻辑上相关的服务。 (即,如果客户可以做A,那么他在逻辑上也可以做B)。

或者,我必须将用户的整个权限集编码为安全性头的一部分。我将不得不调查开销是多少。

编辑:

几个人都提到寻找其他安全方案,例如WS-Security和SAML等我已经有了。事实上,我从WS-Security获得了这个想法。问题是其他方案不提供我需要的功能(缓存授权信息并防止没有中间数据库的重放)。如果有人知道一个方案,那么我会反过来使用它。此外,这是关于认证的而不是。这是由我无法控制的另一种机制处理的。

如果事实证明无法缓存授权数据,那么这意味着我只需承担每个级别的授权开销。

+0

SAML声明如下所示: “客户端X具有角色A和B.此声明在时间T有效,签名,AuthService”。 这不是你所需要的? – ykaganovich 2008-10-05 22:18:31

+0

今天我将重新访问SAML和XACML。 – ilitirit 2008-10-08 12:16:24

回答

1

就我个人而言,只要您有一个集中的底层框架来支持SecurityToken值的验证,我不会看到您有任何问题。

2

好的,用我希望更好的替换旧的答案。

如果您有办法在您的服务之间安全地共享数据,您所描述的内容应该可以工作。例如,如果您的服务与授权服务共享密钥,则可以使用此密钥来获取盐。顺便说一句,我不知道足够多的密码来说明是否足够安全地添加秘密盐+散列(虽然看起来很好);但是,我很确定,使用秘密密钥或私钥对HMAC是安全的。旋转键是一个好主意,所以你仍然有一个主密钥并传播一个新的签名密钥。 (a)你在每个服务中硬编码散列逻辑,(b)服务可能希望从授权服务获取更详细的数据,而不仅仅是一个是/否的答案。例如,您可能希望授权服务将标头中插入此用户属于角色A和B但不属于C.

作为一种替代方法,您可以让授权服务创建一个包含任何有趣信息的新标头有,并签署该块。

此时,我们正在讨论单点登录实施。您已经了解WS-Security规格。我描述的这个头文件听起来很像一个SAML断言。

Here's an article关于使用WS-Security和SAML进行单点登录。

现在,我不知道你是否需要所有这些...也有中间解决方案。例如,授权服务可以签署原始用户名块;如果您担心公/私密码性能,并且您可以共享密钥,您还可以使用密钥来签名而不是公钥/私钥。

4

您的方案的根本问题是您没有使用标准框架或实施。这与您的方案本身的任何特殊优点无关。

原因很简单,安全性(尤其是密码学)非常非常复杂,几乎不可能正确。使用一个强大,易于理解和证明的通用工具。

有关WS-Security的更多信息,请参阅:http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss。大多数框架(.NET/JavaEE等)都会为WS-Security提供内置支持(某种程度上)。

如果您认为您的方案在某些方面比标准更好,我建议您将它写成论文并提交给同行评审(以及参考实施),但不要用它来保护一个应用程序。在 我想你混淆身份验证和授权一点,这是很容易做到的角色......

安全令牌(或类似)的卷:

编辑回应OP编辑方案是验证消息的发送者 - 基本上,他们应该是发件人。正如您正确地指出的那样,身份验证并不意味着发件人将授予访问哪些底层资源。

授权是您通过认证的发件人并应用一些权限集以便限制访问范围的过程。通常,框架默认不会执行授权,您必须通过创建某种形式的ACL来启用它,或者通过扩展某种“安全管理器”类型的界面来启用它。

事实上,这个想法是,认证层会告诉你谁是试图访问页,并离开它你来决定,如果该人被授权访问页面A.

你永远不应该商店有关消息本身的权限和权限的信息 - 接收方应验证针对每条消息的ACL(或数据库或其他)的权限。如果有人想知道如何修改信息,这会限制你的曝光。

+0

你是否看到任何潜在的问题? – ilitirit 2008-10-02 10:55:38

0

首先,阅读@CJP的帖子,他提出了一个很好的和有效的观点。
如果你想继续前进,把它卷反正自己(也许你有一个很好的理由),我会做以下几点:

  • 你在谈论的身份验证服务,而不是授权服务。只是为了确保你知道你在说什么......?
  • 其次,你需要分开盐(这不是秘密)和关键(是)之间。你应该有一个密钥散列(例如HMAC)和salt(或者一个带键的盐味散列,听起来像三明治一样)。正如所指出的那样,盐不是秘密的,但应该为每个标记而改变,并且可以包含在标题中;钥匙必须是秘密的,每天更换都是好的。当然,请确保您使用强散列(如SHA-256),适当的密钥管理技术,等等等等

同样,我希望你重新考虑滚动你自己的,但如果你必须走出去在你自己的...