【问题标题】:Saml Authentication Request Protocol IdSaml 身份验证请求协议 ID
【发布时间】:2011-02-22 10:02:34
【问题描述】:

当使用 SAML2.0 协议进行 Http 重定向绑定时,我应该像这样发送到身份提供者结构:

<q1:AuthnRequest 
         ID="{82AB4AE6-919C-5FE6-C843-8342E6F9AB61}" Version="2.0" 
           IssueInstant="2011-02-22T09:19:48+0100" 
           Destination="https://test.server.com/Service.jsf" 
           IsPassive="false" 
           AssertionConsumerServiceURL="http://myservice.com/sso/" 
          xmlns:q1="urn:oasis:names:tc:SAML:2.0:protocol"> 
          <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">test.server.com</Issuer>
</q1:AuthnRequest>

我的问题是:ID 的值是如何产生的?

ID="{82AB4AE6-919C-5FE6-C843-8342E6F9AB61}" Version="2.0"

生成它的规则是什么?

【问题讨论】:

    标签: security authentication request protocols saml


    【解决方案1】:

    没有明确定义生成 SAML ID 的确切方法——它必须仅符合 XML ID 的标准。 XML ID 是一个 xsd:NCName,它是从 xsd:Name 派生的,它不能以数字开头或包含空格,并且应该具有 160 位的“随机性”。

    满足该标准的 Java 中最简单的 ID 生成器是:

    String id() {
      return "a" + UUID.randomUUID();
    }
    

    此外,OpenSAML 还附带 SecureRandomIdentifierGenerator:

    // You will need to catch the NoSuchAlgorithmException during construction.
    IdentifierGenerator idGenerator = new SecureRandomIdentifierGenerator();
    
    String id() {
      return idGenerator.generateIdentifier();
    }
    

    实际的生成代码如下所示:

    SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    
    String generateIdentifier() {
      return generateIdentifier(16);
    }
    
    String generateIdentifier(int size) {
      byte[] buf = new byte[size];
      random.nextBytes(buf);
      return "_".concat(new String(Hex.encode(buf)));
    }
    

    SAMLSSOUtil 中提取的另一个替代方案:

    char[] charMapping = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' };
    Random random = new Random();
    
    String createID() {
      byte[] bytes = new byte[20]; // 160 bits
      random.nextBytes(bytes);
    
      char[] chars = new char[40];
    
      for (int i = 0; i < bytes.length; i++) {
        int left = (bytes[i] >> 4) & 0x0f;
        int right = bytes[i] & 0x0f;
        chars[i * 2] = charMapping[left];
        chars[i * 2 + 1] = charMapping[right];
      }
    
      return String.valueOf(chars);
    }
    

    来自Oasis 文档:

    xs:ID 简单类型用于声明断言、请求和响应的 SAML 标识符。在本规范中声明为 xs:ID 类型的值除了 xs:ID 类型本身的定义强加的属性外,还必须满足以下属性:

    • 分配标识符的任何一方必须确保该方或任何其他方意外地将相同标识符分配给不同数据对象的可能性可以忽略不计。 • 如果数据对象声明它具有特定标识符,则必须有一个这样的声明。

    SAML 系统实体确保标识符唯一的机制留给实现。在采用随机或伪随机技术的情况下,两个随机选择的标识符相同的概率必须小于或等于 2^-128 并且应该小于或等于 2^-160。可以通过对长度在 128 到 160 位之间的随机选择的值进行编码来满足此要求。编码必须符合定义 xs:ID 数据类型的规则。必须为伪随机生成器播种独特的材料,以确保不同系统之间具有所需的唯一性。

    xs:NCName 简单类型在 SAML 中用于引用 xs:ID 类型的标识符,因为 xs:IDREF 不能用于此目的。在 SAML 中,SAML 标识符引用所引用的元素实际上可能在与使用标识符引用的文档不同的文档中定义。使用 xs:IDREF 将违反其值与同一 XML 文档中某些元素的 ID 属性值匹配的要求。

    【讨论】:

      【解决方案2】:

      id 是从 xsd:Name 派生的 xsd:NCName,不能以数字开头

      Java 中最简单的 id:

      String id = new UID().toString().replaceAll(":", "-");

      并且永远不要将该 id 与任何其他 AuthnRequest 重用,否则如果 IdP 可以检测到,您将收到重放攻击错误

      【讨论】:

        【解决方案3】:

        SAML 2.0 Core 文档的第 1.3.4 节“ID 和 ID 参考值”。

        【讨论】:

          【解决方案4】:

          如何生成它基本上取决于您。唯一需要注意的是它必须是有效的 XML ID 类型值(这意味着它不能以数字开头或包含任何空格)。您需要将其保留在某个地方,以便您可以将其与 IdP 发送的响应相匹配。

          【讨论】:

            【解决方案5】:

            好吧,可能已经晚了,但我认为寻找答案的人可以从中受益......

            你可以参考SAMLUTIL,它有很多标准的 util 方法。 生成 id 可以参考这个 util 中的 createID() 方法。

            【讨论】:

              猜你喜欢
              • 2015-08-24
              • 2011-06-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-07-26
              • 2016-03-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多